Sql-Server
SQL Server 的 is_nullable 有什麼意義嗎?
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;
這只是對使用者的提示嗎?
讓我重新表述這個問題,以確保我們在同一頁面上:
時間戳類型的元數據表示它不接受 NULL,但如果您創建表時未指定可空性,則可以在 INSERT 上為該列指定 NULL。為什麼?
如果您從表中選擇,您將看到在 INSERT 之後該值不為空。您擁有生成的“時間戳”(或 rowversion,如果您更喜歡該名稱)。即,INSERT 上的 NULL 是沒有意義的,這意味著使用了“預設”(可以這麼說)。
可以討論一下時間戳類型的元數據屬性是否應該反映我們是否可以在 INSERT 上指定 null,或者我們最終是否可以在該列中實際具有NULL。
我想,當 Sybase 幾十年前設計系統表時,我們必須在場才能知道答案。我不是。:-)
因此,簡而言之:時間戳類型的列不允許在表中為空,並且基於此可以爭辯說元數據是正確的。
(順便說一句,我首先雖然這是一個向後兼容的東西,所以我啟動了 6.5 版本的 SQL Server 進行測試。我幾乎也啟動了 4.2 版本。但後來我做了一個 SELECT 並沒有直到那時我注意到該值根本不是 NULL。)
這是我使用的 T-SQL(2019 年),FWIW:
USE tempdb DROP TABLE IF EXISTS myTable; DROP TYPE IF EXISTS myTypeYesNull; DROP TYPE IF EXISTS myTypeNoNull; CREATE TYPE myTypeYesNull FROM int NULL; CREATE TYPE myTypeNoNull FROM int NOT NULL; GO CREATE TABLE myTable (yesNull myTypeYesNull, noNull myTypeNoNull, ts timestamp, sname sysname); GO SELECT name, is_nullable FROM sys.types WHERE name IN ('myTypeYesNull', 'myTypeNoNull', 'timestamp', 'sysname') SELECT COLUMNPROPERTY(OBJECT_ID('myTable'), 'yesNull', 'AllowsNull') AS yesNull ,COLUMNPROPERTY(OBJECT_ID('myTable'), 'noNull', 'AllowsNull') AS noNull ,COLUMNPROPERTY(OBJECT_ID('myTable'), 'ts', 'AllowsNull') AS ts ,COLUMNPROPERTY(OBJECT_ID('myTable'), 'sname', 'AllowsNull') AS sname; --The ts column accepts NULL even though table meta-data states differently INSERT INTO myTable (yesNull, noNull, ts, sname) VALUES(NULL, 1, NULL, 'x') SELECT * FROM myTable ---------------------------------------------------------------------- --Code executable on really old versions DROP TABLE myTable GO SELECT name, allownulls FROM systypes WHERE name = 'sysname' CREATE TABLE myTable(ts timestamp NULL) GO --Doesn't fail on 6.5 INSERT INTO myTable(ts) VALUES(null) SELECT * FROM myTable