[英]ISNULL vs CASE Return Type
我最近遇到了一個有趣的問題,即在TSQL中將CASE
語句更改為ISNULL
函數。 我正在使用的查詢用於獲取我工作的網站的一些用戶屬性和權限。 以前,查詢有許多類似於以下內容的CASE
語句:
注意: a.column1
中的a.column1
是表中的bit
類型。 另請注意, [CanDoSomething]
結果列有時用作網站中的字符串。
SELECT
...
CASE
WHEN a.column1 IS NULL THEN 0
ELSE a.column1
END [CanDoSomething]
...
FROM
a
DBA用ISNULL
函數替換了這些CASE
語句:
SELECT
...
ISNULL(a.column1, 0) [CanDoSomething]
...
FROM
a
這似乎是一個很好的改變,但它在C#中檢索數據時引起了一些意想不到的事情。 使用上一個查詢,從C#中的DataTable
訪問時, [CanDoSomething]
列的值為1
或0
。 當我們改為使用ISNULL
,C#中的值隨后被更改為true
或false
,當被視為字符串時,顯然與1
或0
。
這引起的錯誤已經得到解決。 我只是好奇為什么ISNULL
返回的值與等效的CASE
語句不同,我似乎無法在Google上找到任何答案。
答案是在ISNULL
的返回類型的文檔中 :
ISNULL ( check_expression , replacement_value )
返回與
check_expression
相同的類型。 如果提供了一個文字NULL
作為check_expression
,則返回replacement_value的數據類型。 如果提供了一個文字NULL
作為check_expression
並且沒有提供replacement_value
,則返回一個int
。
與總是返回 *的 int
CASE
表達式不同,因為第一個分支中的零返回一個int
, ISNULL
將返回其第一個參數類型的值,即a.column1
。
CASE
表達式是在編輯之前, WHEN a.column1 IS NULL THEN 0 ELSE 1
。
要擴展@ dasblinkenlight的解釋:
真正的問題是,根據文檔 , case
表達
從* result_expressions *和可選的* else_result_expression *中的類型集返回最高優先級類型。 有關更多信息,請參閱數據類型優先級(Transact-SQL) 。
而isnull()
返回與* check_expression *相同的類型
在你的情況下,這是一bit
。 你的case
表達:
CASE
WHEN a.column1 IS NULL THEN 0
ELSE a.column1
END
具有返回兩種不同數據類型的執行路徑,一個int
(文字值0
)和一個bit
(列的值)。 如果查看上面鏈接的數據類型優先級圖表 ,則int
的優先級高於bit
,因此bit
值將轉換為int
。
這是因為從bit
到int
的轉換是擴展轉換 。 Sql Server的bit
類型本質上是1位整數值,因此沒有數據丟失。 從int
到bit
的轉換是一種縮小的轉換,並且存在數據丟失的可能性(至少在概念上)。
你不會遇到這個問題,如果DBA使用了coalesce()
而不是isnull()
,這本來是我個人的選擇,因為coalesce()
被定義為返回類似於case
的類型。 coalesce()
返回具有最高數據類型優先級的表達式的數據類型。 如果所有表達式都不可為空,則結果將輸入為nonnullable。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.