18

我对 SQL/数据库一无所知,但我正在和一位从事大量数据库工作的朋友聊天,了解一些数据库如何使用“布尔”字段,除了 true 和 false 之外,该字段还可以取 NULL 值。

关于这一点,他发表了这样的评论:“值得微软称赞的是,他们从未将这种字段称为布尔值,他们只是将其称为位。这是一个真正的位 - 如果您有八个或更少的位字段在一条记录中,它只需要一个字节来存储它们。”

当然,这对我来说似乎是不可能的——如果该字段可以保存三个值,那么您将不会将其中的八个值放入一个字节中。我的朋友同意这看起来很奇怪,但恳求对底层内部的无知,并说据他所知,从 SQL 端看,这样的字段可以保存三个值,并且确实需要一个字节的存储空间. 我想我们中的一个人有一根电线交叉。谁能解释这里到底发生了什么?

4

5 回答 5

21

我建议阅读这篇文章以获得对空存储的一个很好的解释:SQL Server 如何真正存储 NULL-s。简而言之,空/非空位存储在不同的位置,即行的空位图。

来自文章:

对于允许空值的列,每一行都有一个空位图。如果该列中的行为空,则位图中的位为 1,否则为 0。

因此,虽然 8 位列的实际存储在 1 个字节中,但行的空位图中还有额外的位指示该列是否为 NULL……所以取决于您的计数方式。为了完全准确,8 位列使用2 个字节,只是分成 2 个不同的位置。

于 2010-06-02T03:08:37.913 回答
7

空指示符是单独存储的,所以一个可空位实际上需要两个位。严格来说,“null”不是第三个值;它有点像一个占位符,上面写着“这里可能有一个值,但我们不知道它是什么。” 所以如果某位为空,你可以将它与true比较,比较会失败,但你也可以将它与false比较,比较会失败。

于 2010-06-02T03:07:43.030 回答
3

你是对的。您可以将八个真/假值打包到一个字节中,但您仍然需要额外的存储空间来指示它是否为 NULL。仅用 2 8表示 3 8个不同的状态是不可能的。

于 2010-06-02T03:08:04.370 回答
2

你的朋友是对的,但同时也是错的。BIT 字段可能被认为能够维护三个不同的值,但根据定义 NULL 是没有值。

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

于 2010-06-02T03:12:00.557 回答
1

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

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

于 2010-06-02T07:36:17.467 回答