微软可以在一个比特中存储三值字段吗?

18

我完全不了解SQL/数据库,但我正在与一位做大量数据库工作的朋友聊天,关于一些数据库使用“布尔”字段的方式,该字段除了真和假之外还可以取值为NULL。

关于这一点,他发表了这样的评论:“值得称赞的是,微软从来没有将那种字段称为布尔,他们只称其为位(bit)。而且它是一个真正的位(bit) - 如果在记录中有八个或更少的位(bit)字段,则仅需要一个字节即可存储所有字段。”

自然地,这对我来说似乎是不可能的 - 如果该字段可以容纳三个值,您不会把八个它们都放进一个字节里。我的朋友同意这似乎很奇怪,但是对底层内部一无所知,并表示就他所知,从SQL方面看,这样的字段可以容纳三个值,并确实需要一个字节的存储空间。我想我们其中有一个存在误解。有人能解释一下这里到底发生了什么吗?


18
Jon Skeet 可以用一个比特位存储三值字段。 - Dean Harding
1
该死,我应该早就预见到这个问题! - fenomas
5个回答

22

我建议阅读这篇文章,了解有关null存储的良好解释:SQL Server到底是如何存储NULL值。简而言之,null/not null位存储在不同的位置,即行的null bitmap中。

引用该文章内容:

每一行都有一个null bitmap,用于存储允许为空的列。如果该列的行为null,则在bitmap中的一位为1,否则为0。

因此,虽然8位列的实际值存储在1个字节中,但行的null bitmap中有额外的位指示该列是否为NULL...所以这取决于您如何计数。要完全准确,8位列使用2个字节,只是分成了两个不同的位置。


啊,我就知道一定是这样的。感谢提供详细信息的链接! - fenomas
你的声望增长必须是SO上增长最高的之一。我对你的声望曲线斜率感到很好奇! - Mitch Wheat
@Mitch - 哈哈,我有一段时间没有检查它了,这很酷,谢谢你指出 :) - Nick Craver

7

空指示器被单独存储,所以可空位实际上需要两位。严格来说,“null”不是第三个值;它更像是一个占位符,表示“这里可能有一个值,但我们不知道是什么”。因此,如果一个位为null,你可以将其与true进行比较,比较会失败,但你也可以将其与false进行比较,比较同样会失败。


3

你说得没错。你可以将八个真/假值打包成一个字节,但你仍需要额外的存储空间来指示它是否为NULL。用只有2的8次方的状态表示3的8次方个不同状态是不可能的。


2

您的朋友说得没错,但同时也有些错误。BIT字段可以被认为具有三个不同的值,但是根据定义,NULL是没有值的。

此外,允许在位字段上使用NULL意味着该字段将使用2位(一个用于值,一个用于判断是否为NULL)。但是,字段的NULL状态(NULL Bit)存储在行的位图中,而不是在给定列的确切内存空间中。


1

其他人已经说过,BIT需要2个位而不是一个。

另一个经常被忽视的重要点:在SQL Server中,Bit不是布尔或逻辑数据类型;它是数字(整数)数据类型。"一个整数数据类型,可以取值为1、0或NULL"。Bit仅支持数字运算符(<,>,+,-)。它不支持任何逻辑运算符(AND,OR,NOT等)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接