解剖SQLSERVER 第五篇 OrcaMDF里读取Bits类型数据(译)
解剖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个位
我们再添加一些列
<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已经满了
当读取行记录里的位类型时我们需要知道的状态
很明显,我们一次不能只读取一个字段的值,我们读取固定长度数据类型的时候还需要读取定长数据偏移指针
我们需要一些能在读取的时候指示我们当前读取到字节中哪一个位属于哪一个字段的状态,然后我们读取一个新的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>
第五篇完

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

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

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

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

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

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

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

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

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