Sql-Server
為什麼在視圖中選擇查詢中完全確定性和包羅萬象的“案例”的結果可以為空?
我有一個表,
Id
作為主鍵。create table Anything ( Id bigint not null primary key identity(1, 1) )
當我在 中查看這張表時
Object Explorer
,我當然會看到這張圖片:如您所見, column
Id
不是null。然後我在這個虛擬表上創建一個虛擬視圖:
create view IdIsTwoView as select Id, ( case when Id = 2 then cast(1 as bit) else cast(0 as bit) end ) as IdIsTwo from Anything
但是這一次,在對象資源管理器中我看到了這個結果:
如您所見,儘管我的
case
子句包羅萬象,涵蓋了所有記錄的 100%,並且對所有記錄都有答案,但它是可以為空的。為什麼 SQL Server 會有這種奇怪的行為?以及如何強制它不為 null?
PS我們有一個動態生成程式碼的基礎設施,這種行為給我們帶來了麻煩,我們必須手動將
bool?
C# 中的所有類型更改為bool
.
要回答您的實際問題-我不知道。我的猜測是解析器可以直接檢查列以確定可空性。如果列引用和輸出之間存在任何可能影響可空性的內容(例如函式或表達式),則假定輸出可以為空。MS 根本沒有編寫程式碼來深入檢查所有情況並推理結果。他們也和其他人一樣有預算、時間表和積壓工作。這根本沒有被優先考慮。
不過,這個假設讓我思考。如果它可以解釋列,它可以推理什麼結構?如果我可以為它提供一個足夠簡單且保證不為空的表達式,它是否會產生所需的輸出。答案是肯定的,使用ISNULL:
create or alter view IdIsTwoView as select Id, ( case when Id = 2 then cast(1 as bit) else cast(0 as bit) end ) as IdIsTwo, isnull( case when Id = 2 then cast(1 as bit) else cast(0 as bit) end , -1) as X from Anything;
我選擇 -1 作為替換值,因為它超出了標識的範圍,所以如果看到它會是一個明顯的錯誤。我想,任何常數都會起作用。