Sql-Server

為什麼在視圖中選擇查詢中完全確定性和包羅萬象的“案例”的結果可以為空?

  • March 22, 2020

我有一個表,Id作為主鍵。

create table Anything
(
   Id bigint not null primary key identity(1, 1)
)

當我在 中查看這張表時Object Explorer,我當然會看到這張圖片:

在此處輸入圖像描述

如您所見, columnId不是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 作為替換值,因為它超出了標識的範圍,所以如果看到它會是一個明顯的錯誤。我想,任何常數都會起作用。

引用自:https://dba.stackexchange.com/questions/262424