为啥可以为空的 rowversion 列在语义上等同于 varbinary(8)?

Posted

技术标签:

【中文标题】为啥可以为空的 rowversion 列在语义上等同于 varbinary(8)?【英文标题】:Why is a nullable rowversion column is semantically equivalent to a varbinary(8)?为什么可以为空的 rowversion 列在语义上等同于 varbinary(8)? 【发布时间】:2013-06-03 17:06:27 【问题描述】:

MSDN page 声明:

一个不可为空的 rowversion 列在语义上等价于 二进制(8)列。可为空的 rowversion 列在语义上是 相当于一个 varbinary(8) 列。

鉴于不可为空的 rowversion 列在语义上等同于 binary(8) 列,为什么说可空的 rowversion 列在语义上等同于 varbinary(8) 列而不是可空的 binary(8) 列?

这是否意味着可为空的 rowversion 列在语义上不等同于可为空的 binary(8) 列?

我的特定示例是,我将有一个包含其他表行的副本的表。一些源表具有行版本,而另一些则没有。因此,我的表中的“rowversion”列必须接受空值。我想了解为什么(或是否)该列应该是 varbinary(8) null 而不是 binary(8) null。

【问题讨论】:

@Andomar 我更新了我的问题来解释我为什么想知道。 binary(8) 类型的列将始终包含 8 个字节的存储空间 - 无论其中存储什么 - 甚至是 NULL。一个可以为空的版本 - varbinary(8) - 但是将只占用真正需要的空间(加上一些开销)。 我认为这里的文档是错误的。即使表被声明为ROWVERSION NULL,它也存储在行的固定长度部分。 @marc_s 它可以为空吗?尽管显式插入了NULLCREATE TABLE #T(C ROWVERSION NULL);INSERT INTO #T VALUES(NULL);SELECT * FROM #T;DROP TABLE #T 仍然返回NOT NULL @marc_s 对不起,我想我明白你原来的评论是什么意思。在 OP 的目标表中,如果他们希望大多数是 NOT NULL,他们应该声明 binary,因为 varbinary 有两个字节的额外开销,但如果大多数为空,他们可以节省空间。那么@Ɖiamond ǤeezeƦ 有多少行将包含此值? @ƉiamondǤeezeƦ:我想只要你的比例超过 25%(varbinary 数据类型的开销),我就会选择 varbinary(8) 【参考方案1】:

二进制(8)是一个正好有 8 个字节的二进制文件。 varbinary(8) 是一个最多有 8 个字节的二进制文件。 空值是 0 个字节。 它必须是可以有 0 或 8 个字节的形式。 因此它必须是 varbinary。

【讨论】:

呃……我不买。具体来说,我可以有一个可为空的 binary(8) (或任何其他固定宽度的数据类型)。 什么不能买?空值记录在数据行的单独字节上的各个位中。第一个可为空的列向存储添加一个字节,此后每八个可为空的列向存储添加一个字节。 'Null ness' 形象地存储在行的'header' 上。一旦添加了 null 位使其为 null,它就具有与 varbinary 相同的存储空间。 我是说列的可为空特性以及它是否是可变长度列是正交概念。具体到这种情况,为什么 rowversion 列的可空性必然意味着它是 varbinay(8) NULL 而不是 binary(8) null?前者意味着它可以是任何长度的二进制值,最多(包括)8 个字节(或 null),而后者意味着它可以是 8 个字节(或 null)的二进制值。

以上是关于为啥可以为空的 rowversion 列在语义上等同于 varbinary(8)?的主要内容,如果未能解决你的问题,请参考以下文章

过滤 PIG LATIN 脚本中的列在为空的单元格上插入来自其他列的数据

为啥Required IdentityUser 属性会导致可以为空的数据库字段?

在 PySpark 数据框中添加可为空的列

为啥 TargetNullValue 更新可为空的 Source

为啥 all() 为空的可迭代对象返回 True? [复制]

为啥检查字符串是不是为空的函数总是返回true? [关闭]