目錄
解剖SQLSERVER 第五篇  OrcaMDF里读取Bits类型数据(译)
首頁 資料庫 mysql教程 解剖SQLSERVER 第五篇 OrcaMDF里读取Bits类型数据(译)

解剖SQLSERVER 第五篇 OrcaMDF里读取Bits类型数据(译)

Jun 07, 2016 pm 03:19 PM
bit sqlserver 讀取

解剖SQLSERVER 第五篇 OrcaMDF里读取Bits类型数据(译) http://improve.dk/reading-bits-in-orcamdf/ Bits类型的存储跟SQLSERVER其他定长数据类型的存储很不一样。通常,所有定长列都会显示出来,一个条记录里定长数据部分的字段数据总是一个挨着一个 我们

解剖SQLSERVER 第五篇  OrcaMDF里读取Bits类型数据(译)

http://improve.dk/reading-bits-in-orcamdf/

Bits类型的存储跟SQLSERVER其他定长数据类型的存储很不一样。通常,所有定长列都会显示出来,一个条记录里定长数据部分的字段数据总是一个挨着一个

我们可以写入磁盘的最小数据单位是一个字节,存储位类型数据的天真的方法就是使用一整个(字节@)来存储每一个位,使用常用的格式去解释位类型数据是很简单的

,不过这会浪费一些空间 ,就像null位图,如果一个表只有3列,那么用一个字节来存储null位图会比较浪费,因为其他的5个位都没有用到

@:文章里是用位 ,这里应该是用字节吧

 

在记录的内部位类型是如何存储的?

一些位类型列的值是存储在一个字节中的,最大可以到8个位,通常,我们会有如下表定义

<span>CREATE</span> <span>TABLE</span><span> BitTest
(
    A </span><span>bit</span><span>
    B </span><span>bit</span><span>
    C </span><span>bit</span><span>
    D </span><span>int</span><span>
)</span>
登入後複製

记录的定长部分数据需要占用5个字节,4个字节存储int 列 ,而另一个字节存储A 、B、C这三列位类型的数据,只用了字节里面的3个位

解剖SQLSERVER 第五篇  OrcaMDF里读取Bits类型数据(译)

我们再添加一些列

<span>CREATE</span> <span>TABLE</span><span> BitTest
(
    A </span><span>bit</span><span>
    B </span><span>bit</span><span>
    C </span><span>bit</span><span>
    D </span><span>int</span><span>
    E </span><span>bit</span><span>
    F </span><span>bit</span><span>
    G </span><span>bit</span><span>
    H </span><span>smallint</span><span>
    I </span><span>bit</span><span>
    J </span><span>bit</span><span>
    K </span><span>bit</span><span>
)</span>
登入後複製

E到G列按道理来说应该存储在D列的后面,但是他们会继续使用第一个 bit byte,直到第一个 bit byte使用完所有的位空间为止

下面的图显示了H列(smallint )直接存储在D列的后面,而在D列后面是存储K列的新bit byte,因为第一个bit byte已经满了

解剖SQLSERVER 第五篇  OrcaMDF里读取Bits类型数据(译)

 

当读取行记录里的位类型时我们需要知道的状态

很明显,我们一次不能只读取一个字段的值,我们读取固定长度数据类型的时候还需要读取定长数据偏移指针

我们需要一些能在读取的时候指示我们当前读取到字节中哪一个位属于哪一个字段的状态,然后我们读取一个新的bit byte

我来介绍一下RecordReadState类

<span>public</span> <span>class</span><span> RecordReadState
{
    </span><span>//</span><span> We start out having consumed all bits as none have been read</span>
    <span>private</span> <span>int</span> currentBitIndex = <span>8</span><span>;
    </span><span>private</span> <span>byte</span><span> bits;

    </span><span>public</span> <span>void</span> LoadBitByte(<span>byte</span><span> bits)
    {
        </span><span>this</span>.bits =<span> bits;
        currentBitIndex </span>= <span>0</span><span>;
    }

    </span><span>public</span> <span>bool</span><span> AllBitsConsumed
    {
        </span><span>get</span> { <span>return</span> currentBitIndex == <span>8</span><span>; }
    }

    </span><span>public</span> <span>bool</span><span> GetNextBit()
    {
        </span><span>return</span> (bits & (<span>1</span> 0<span>;
    }
}</span>
登入後複製

RecordReadState 类当前只需要处理bits,但是将来我可能还要创建一个BitReadState 类用来保存读取状态

RecordReadState 类保存了一个字节用来当作指针指出下一个可用的位在字节的哪个地方,如果字节已经用完了存储满了所有的位数据

(currentBixIndex = 8 (0-7 being the available bits)),方法AllBitsConsumed 就会返回true,指示我们需要读取一个新的 bit byte

GetNextBit方法只是简单的从 bit byte中读取当前的bit ,然后将currentBitIndex(bit index)的值加1

demo

<span>using</span><span> NUnit.Framework;
</span><span>using</span><span> OrcaMDF.Core.Engine.Records;
</span><span>namespace</span><span> OrcaMDF.Core.Tests.Engine.Records
{
    [TestFixture]
</span><span>public</span> <span>class</span><span> RecordReadStateTests
{
        [Test]
</span><span>public</span> <span>void</span><span> General()
{
</span><span>var</span> state = <span>new</span><span> RecordReadState();
</span><span>//</span><span> No bits available</span>
<span>Assert.IsTrue(state.AllBitsConsumed);
state.LoadBitByte(</span><span>0xD2</span>); <span>//</span><span> 11010010
</span><span>//</span><span> Bits available</span>
<span>Assert.IsFalse(state.AllBitsConsumed);
</span><span>//</span><span> Reading bit values</span>
<span>Assert.IsFalse(state.GetNextBit());
Assert.IsTrue(state.GetNextBit());
Assert.IsFalse(state.GetNextBit());
Assert.IsFalse(state.GetNextBit());
Assert.IsTrue(state.GetNextBit());
Assert.IsFalse(state.GetNextBit());
Assert.IsTrue(state.GetNextBit());
</span><span>//</span><span> One bit left</span>
<span>Assert.IsFalse(state.AllBitsConsumed);
Assert.IsTrue(state.GetNextBit());
</span><span>//</span><span> Bits exhausted, ready for next byte</span>
<span>Assert.IsTrue(state.AllBitsConsumed);
}
}
}</span>
登入後複製

 

SqlBit实现

一旦我们实现了状态的读取,我们就可以实现SqlBit 类型

<span>public</span> <span>class</span><span> SqlBit : ISqlType
{
    </span><span>private</span> <span>readonly</span><span> RecordReadState readState;

    </span><span>public</span><span> SqlBit(RecordReadState readState)
    {
        </span><span>this</span>.readState =<span> readState;
    }

    </span><span>public</span> <span>bool</span><span> IsVariableLength
    {
        </span><span>get</span> { <span>return</span> <span>false</span><span>; }
    }

    </span><span>public</span> <span>short</span>?<span> FixedLength
    {
        </span><span>get</span><span>
        {
            </span><span>if</span><span> (readState.AllBitsConsumed)
                </span><span>return</span> <span>1</span><span>;

            </span><span>return</span> <span>0</span><span>;
        }
    }

    </span><span>public</span> <span>object</span> GetValue(<span>byte</span><span>[] value)
    {
        </span><span>if</span>(readState.AllBitsConsumed && value.Length != <span>1</span><span>)
            </span><span>throw</span> <span>new</span> ArgumentException(<span>"</span><span>All bits consumed, invalid value length: </span><span>"</span> +<span> value.Length);

        </span><span>if</span> (value.Length == <span>1</span><span>)
            readState.LoadBitByte(value[</span><span>0</span><span>]);

        </span><span>return</span><span> readState.GetNextBit();
    }
}</span>
登入後複製

SqlBit 在构造函数里传入一个read state,read state指示当前记录读取操作的范围。需要注意的是固定长度需要依据read state里的当前AllBitsConsumed值

如果字节里面所有位都被占用,那么意味着需要读取整个字节,如果if (readState.AllBitsConsumed)返回0表示不需要读取整个字节,但是GetValue方法依然会被调用

GetValue方法会验证一种情况:readState.AllBitsConsumed 返回真,证明 bit byte是有数据存储在里面,但是value.Length返回的长度是0,那证明有问题了

如果我们读到一个值,我们会请求 read state 去装载一个新的bit byte ,之后,我们可以调用GetNextBit 方法返回 read state的当前bit

相关测试

<span>using</span><span> NUnit.Framework;
</span><span>using</span><span> OrcaMDF.Core.Engine.Records;
</span><span>using</span><span> OrcaMDF.Core.Engine.SqlTypes;

</span><span>namespace</span><span> OrcaMDF.Core.Tests.Engine.SqlTypes
{
    [TestFixture]
    </span><span>public</span> <span>class</span><span> SqlBitTests
    {
        [Test]
        </span><span>public</span> <span>void</span><span> GetValue()
        {
            </span><span>var</span> readState = <span>new</span><span> RecordReadState();
            </span><span>var</span> type = <span>new</span><span> SqlBit(readState);

            </span><span>//</span><span> No bytes read - length is one</span>
            Assert.AreEqual(<span>1</span><span>, type.FixedLength);

            </span><span>//</span><span> Load byte and check length is 0</span>
            readState.LoadBitByte(<span>0xD2</span><span>);
            Assert.AreEqual(</span><span>0</span><span>, type.FixedLength);

            Assert.IsFalse((</span><span>bool</span>)type.GetValue(<span>new</span> <span>byte</span>[<span>0</span><span>]));
            Assert.IsTrue((</span><span>bool</span>)type.GetValue(<span>new</span> <span>byte</span>[<span>0</span><span>]));
            Assert.IsFalse((</span><span>bool</span>)type.GetValue(<span>new</span> <span>byte</span>[<span>0</span><span>]));
            Assert.IsFalse((</span><span>bool</span>)type.GetValue(<span>new</span> <span>byte</span>[<span>0</span><span>]));
            Assert.IsTrue((</span><span>bool</span>)type.GetValue(<span>new</span> <span>byte</span>[<span>0</span><span>]));
            Assert.IsFalse((</span><span>bool</span>)type.GetValue(<span>new</span> <span>byte</span>[<span>0</span><span>]));
            Assert.IsTrue((</span><span>bool</span>)type.GetValue(<span>new</span> <span>byte</span>[<span>0</span><span>]));

            </span><span>//</span><span> One bit left - length should still be 0</span>
            Assert.AreEqual(<span>0</span><span>, type.FixedLength);

            Assert.IsTrue((</span><span>bool</span>)type.GetValue(<span>new</span> <span>byte</span>[<span>0</span><span>]));

            </span><span>//</span><span> All bits consumed - length should be 1</span>
            Assert.AreEqual(<span>1</span><span>, type.FixedLength);
        }
    }
}</span>
登入後複製

 

第五篇完

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

sqlserver怎麼匯入mdf文件 sqlserver怎麼匯入mdf文件 Apr 08, 2024 am 11:41 AM

匯入步驟如下:將 MDF 檔案複製到 SQL Server 的資料目錄(通常為 C:\Program Files\Microsoft SQL Server\MSSQL\DATA)。在 SQL Server Management Studio(SSMS)中,開啟資料庫並選擇「附加」。點選“新增”按鈕,選擇 MDF 檔案。確認資料庫名稱,點選確定按鈕即可。

sqlserver資料庫中已存在名為的物件怎麼解決 sqlserver資料庫中已存在名為的物件怎麼解決 Apr 05, 2024 pm 09:42 PM

對於 SQL Server 資料庫中已存在同名對象,需要採取下列步驟:確認物件類型(表格、檢視、預存程序)。如果物件為空,可使用 IF NOT EXISTS 跳過建立。如果物件有數據,使用不同名稱或修改結構。使用 DROP 刪除現有物件(謹慎操作,建議備份)。檢查架構更改,確保沒有引用刪除或重新命名的物件。

怎麼查看sqlserver連接埠號 怎麼查看sqlserver連接埠號 Apr 05, 2024 pm 09:57 PM

若要查看 SQL Server 連接埠號碼:開啟 SSMS,連線到伺服器。在物件資源管理器中找到伺服器名稱,右鍵單擊它,然後選擇“屬性”。在「連線」標籤中,查看「TCP 連接埠」欄位。

sqlserver服務無法啟動怎麼辦 sqlserver服務無法啟動怎麼辦 Apr 05, 2024 pm 10:00 PM

當 SQL Server 服務無法啟動時,可採取下列步驟解決:檢查錯誤日誌以確定根本原因。確保服務帳戶具有啟動服務的權限。檢查依賴項服務是否正在執行。禁用防毒軟體。修復 SQL Server 安裝。如果修復不起作用,重新安裝 SQL Server。

sqlserver誤刪資料庫怎麼恢復 sqlserver誤刪資料庫怎麼恢復 Apr 05, 2024 pm 10:39 PM

若誤刪 SQL Server 資料庫,可採取下列步驟還原:停止資料庫活動;備份日誌檔案;檢查資料庫日誌;復原選項:從備份還原;從交易日誌還原;使用 DBCC CHECKDB;使用第三方工具。請定期備份資料庫並啟用交易日誌以防止資料遺失。

sqlserver資料庫在哪裡 sqlserver資料庫在哪裡 Apr 05, 2024 pm 08:21 PM

SQL Server 資料庫檔案通常儲存在下列預設位置:Windows: C:\Program Files\Microsoft SQL Server\MSSQL\DATALinux: /var/opt/mssql/data可透過修改資料庫檔案路徑設定來自訂資料庫檔案位置。

如何使用pandas正確讀取txt文件 如何使用pandas正確讀取txt文件 Jan 19, 2024 am 08:39 AM

如何使用pandas正確讀取txt文件,需要具體程式碼範例Pandas是一個廣泛使用的Python資料分析函式庫,它可以用來處理各種各樣的資料類型,包括CSV檔案、Excel檔案、SQL資料庫等。同時,它也可以用於讀取文字文件,例如txt文件。但是,在讀取txt檔案時,我們有時會遇到一些問題,例如編碼問題、分隔符號問題等。本文將介紹如何使用pandas正確讀取txt

sqlserver安裝失敗怎麼樣刪除乾淨 sqlserver安裝失敗怎麼樣刪除乾淨 Apr 05, 2024 pm 11:27 PM

如果 SQL Server 安裝失敗,可透過下列步驟清理:解除安裝 SQL Server刪除註冊表項刪除檔案和資料夾重新啟動計算機

See all articles