SQL Server 有一个类型标志,称为is_nullable
您可以在sys.types
. 目前,(SQL Server 2019)它只设置为FALSE
两种类型,sys.timestamp
和sys.sysname
. 对sys.timestamp
这种类型似乎接受null
。在sys.sysname
它没有。这种行为有什么解释吗?
你可以看到这些类型
SELECT * FROM sys.types WHERE is_nullable = 0;
SELECT TYPEPROPERTY('timestamp', 'AllowsNull'); -- returns 0
你可以像这样使用它,
CREATE TABLE foo ( a sys.timestamp );
INSERT INTO foo (a) VALUES ( null );
请注意,如果您使用,这将不起作用sys.sysname
Msg 515 Level 16 State 2 Line 1 Cannot insert the value NULL into column 'a', table 'dbo.foo'; column does not allow nulls. INSERT fails. Msg 3621 Level 0 State 0 Line 1 The statement has been terminated.
如果您创建用户定义的数据类型,它也将不起作用,NOT NULL
CREATE TYPE bar FROM int NOT NULL;
这只是对用户的提示吗?
你的问题的答案是肯定的。
该列指定数据类型的默认可空性,如果用户不表达偏好,例如在具有显式或规范的
CREATE TABLE
语句中,这可能很重要。可悲的是,该信息仅存在于旧兼容性视图的文档中:NULL
NOT NULL
sys.systypes
例如,可以覆盖该类型的默认
NOT NULL
行为sysname
:timestamp
类型(首选名称rowversion
)由于其用于检测行更改而具有额外的特殊行为。有关更多详细信息,请参见其他答案。您仍然可以以相同的方式覆盖其可空性,但实际上无法为时间戳/行版本属性存储 NULL。有几个复杂的层来确定属性可空性。我不在这里重复一些细节,而是向您推荐为什么您应该始终指定列是否接受Phil 因子的空值以获取背景信息和其他阅读材料。
让我重新表述这个问题,以确保我们在同一页面上:
时间戳类型的元数据表示它不接受 NULL,但如果您创建表时未指定可空性,则可以在 INSERT 上为该列指定 NULL。为什么?
如果您从表中选择,您将看到在 INSERT 之后该值不为空。您拥有生成的“时间戳”(或 rowversion,如果您更喜欢该名称)。即,INSERT 上的 NULL 是没有意义的,这意味着使用了“默认”(可以这么说)。
可以讨论一下时间戳类型的元数据属性是否应该反映我们是否可以在 INSERT 上指定 null,或者我们最终是否可以在该列中实际具有NULL。
我想,当 Sybase 几十年前设计系统表时,我们必须在场才能知道答案。我不是。:-)
因此,简而言之:时间戳类型的列不允许在表中为空,并且基于此可以争辩说元数据是正确的。
(顺便说一句,我首先虽然这是一个向后兼容的东西,所以我启动了 6.5 版本的 SQL Server 进行测试。我几乎也启动了 4.2 版本。但后来我做了一个 SELECT 并没有直到那时我注意到该值根本不是 NULL。)
这是我使用的 T-SQL(2019 年),FWIW: