目录
解剖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脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++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 10:00 PM

当 SQL Server 服务无法启动时,可采取以下步骤解决:检查错误日志以确定根本原因。确保服务帐户具有启动服务的权限。检查依赖项服务是否正在运行。禁用防病毒软件。修复 SQL Server 安装。如果修复不起作用,重新安装 SQL Server。

怎么查看sqlserver端口号 怎么查看sqlserver端口号 Apr 05, 2024 pm 09:57 PM

要查看 SQL Server 端口号:打开 SSMS,连接到服务器。在对象资源管理器中找到服务器名称,右键单击它,然后选择“属性”。在“连接”选项卡中,查看“TCP 端口”字段。

sqlserver数据库在哪里 sqlserver数据库在哪里 Apr 05, 2024 pm 08:21 PM

SQL Server 数据库文件通常存储在以下默认位置:Windows: C:\Program Files\Microsoft SQL Server\MSSQL\DATALinux: /var/opt/mssql/data可通过修改数据库文件路径设置来自定义数据库文件位置。

sqlserver误删数据库怎么恢复 sqlserver误删数据库怎么恢复 Apr 05, 2024 pm 10:39 PM

若误删 SQL Server 数据库,可采取以下步骤恢复:停止数据库活动;备份日志文件;检查数据库日志;恢复选项:从备份恢复;从事务日志恢复;使用 DBCC CHECKDB;使用第三方工具。请定期备份数据库并启用事务日志以防止数据丢失。

sqlserver安装失败怎么样删除干净 sqlserver安装失败怎么样删除干净 Apr 05, 2024 pm 11:27 PM

如果 SQL Server 安装失败,可通过以下步骤清理:卸载 SQL Server删除注册表项删除文件和文件夹重启计算机

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

如何使用pandas正确读取txt文件,需要具体代码示例Pandas是一个广泛使用的Python数据分析库,它可以用于处理各种各样的数据类型,包括CSV文件、Excel文件、SQL数据库等。同时,它也可以用于读取文本文件,例如txt文件。但是,在读取txt文件时,我们有时会遇到一些问题,例如编码问题、分隔符问题等。本文将介绍如何使用pandas正确读取txt

See all articles