为啥可以为空的 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 它可以为空吗?尽管显式插入了NULL
,CREATE 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 属性会导致可以为空的数据库字段?
为啥 TargetNullValue 更新可为空的 Source