【工作雷包】MSSQL IF 0 = '' 會是True!!??

今天在測Stored Procedure時,一直鬼打牆,其中有一段 IF @ID = '',@ID是0,卻判斷為True了...
What the F....🤬

後來才發現,原來SQL Server有資料類型優先順序這檔事。
以下擷取MS Docs

當一個運算子結合不同資料類型的運算式時,低優先順序資料類型會先轉換為高優先順序資料類型。 如果轉換不是支援的隱含轉換,就會傳回錯誤。若運算子結合的運算元運算式具有相同資料類型,則作業結果就含有該資料類型。

詳細優先順序請詳見連結:資料類型優先順序 (Transact-SQL)
所以不理解這個特性時,下列Script就會被雷到

DECLARE @ID INT = 0
IF ISNULL(@ID, '') = ''
BEGIN
    PRINT N'@ID = NULL'
END
ELSE
BEGIN
    PRINT N'@ID <> NULL'
END


原因為@ID是INT,空字串「''」是VARCHAR,而INT的優先順序等級比空字串VARCHAR還要高。

因此VARCHAR會被隱含轉換(IMPLICT CONVERT)為INT。
空字串CONVERT成INT時,會變成0,故證明「0 = ''」

 

延伸議題

基於上述說明,在查資料庫也一樣,若不是用正確的資料類型去查資料,可能會發生效能問題。
假設資料庫要查詢的欄位,其資料類型優先順序較高,則只有輸入參數的類型會被轉型。
但若輸入參數的資料類型優先順序較高,則是資料表欄位會被轉型,再與輸入條件比較,這樣就會效能不佳。

以AdventureWorks範例資料庫來驗證
若傳入為VARCHAR,資料表內欄位為NVARCHAR,因為NVARCHAR高於VARCHAR,故會針對傳入參數做隱含轉換。

為了測試比對,我新增一欄位為VARCHAR,將傳入參數改為NVARCHAR,我們來看看執行計畫。
果然,從執行計畫得知,圖中的語法,會將資料庫的欄位DataCode自動隱含轉換類型,再與輸入參數比對,
若筆數很多,就會發生查詢緩慢的現象。

結論

比對時,要正確使用資料型別。 

 

創用 CC 授權條款
本著作由Chenting Weng製作,以創用CC 姓名標示 4.0 國際 授權條款釋出。
This work by Chenting Weng is licensed under a Creative Commons Attribution 4.0 International License.
Based on a work at https://dotblogs.com.tw/chentingw.

部分文章內容會引用到其他網站的簡介或圖片,若有侵犯到您的著作權,請留言告知,本人會儘快移除。
免責聲明:文章屬個人記事使用,僅供參考,若引用文章造成一切損失,本人不承擔任何責任。如有錯誤,歡迎留言告知。

Part of the content of the article will refer to the profile or picture of other websites.
If there is any infringement of your copyright, please leave a message and let me remove it as soon as possible.
Disclaimer:The article is for personal use and is for reference only. I will not bear any responsibility for any loss caused by quoting the article. If there is an error, please leave a message to inform.