在SQL SERVER 中邏輯表達式存在三種值:TRUE+FALSE+UNKNOWN。UNKNOW可以理解為不確定,既不是TRUE又不是FALSE的表達式,主要由與NULL相關的邏輯判斷引起,值為NULL就意味著該未賦值或該值未確定。
與NULL值做算術運算時,其結果是NULL,如果1+NULL結果為NULL
SQL Server不同場景下對UNKNOWN處理不同,對NULL的處理也不同。
1. 在WHERE+ON+HAVING三種篩選器中,所有運算結果非TURE(FALSE 與UNKNOW)的記錄都不會返回;
2. 在CHECK約束中,所有運算結果為非FALSE(TRUE與UNKNOW)的都屬于滿足CHECK約束的;
3. 在UNIQUE約束中,如果列定義未限制為NOT NULL,那么允許該列存在一條NULL值,如果另外插入或更新一條記錄為NULL時,會違法UNIQUE約束,NULL與NULL是相等的;
4. 在GROUP BY中,NULL值被認為相同而分為一組,NULL與NULL是相等的;
5. 在ORDER BY中,NULL值被認為相同而排列在一起,所有NULL值比已知值小,NULL與NULL是相等的;
除上述3/4/5條中提到的情況外,NULL與NULL是不相等的。
默認情況下,即SET ANSI_NULLS ON時,對于條件(WHERE C1 = NULL)這種查詢,C1列值為NULL的行不會被返回;
而當SET ANSI_NULLS ON時,對于條件(WHERE C1 = NULL)這種查詢,C1列值為NULL的行會被返回,此時C1=NULL應該被理解為做C1 IS NULL 運算,而不應該理解為NULL與NULL相等;
理解混亂的同學可以做以下測試:
--==========================================--生成測試數據DECLARE @TB TABLE( C1 INT)INSERT INTO @TBSELECT 1UNIONSELECT NULL--===========================================--修改默認選項值,設置ANSI_NULLS--注意該設置是回話級別,而不是批處理級別或語句級別SET ANSI_NULLS OFF;--============================================--當ANSI_NULLS OFF時,C1=NULL 等同于C1 IS NULL--因此查詢返回一條NULL的記錄SELECT * FROM @TBWHERE C1=NULL--============================================--當ANSI_NULLS OFF,NULL與NULL仍不認為相等--因此查詢中不會返回NULL的記錄SELECT * FROM @TB AS TB1INNER JOIN @TB TB2ON TB1.C1=TB2.C1
運行結果為:
為規范操作和避免混亂,強烈建議使用IS NULL 和IS NOT NULL判斷值是否為NULL,避免修改默認選項ANSI_NULLS為OFF。
除上面提到的特殊情況外,由于NULL與NULL是不相等的,因此
1. 在做IN和EXISTS運算如WHERE C1 IN(SELECT ID FROM TB1) 或者 WHERE EXISTS (SELECT ID FROM TB1 WHERE ID =C1)時,所有C1列為NULL的行都不會被返回,無論表TB1的ID列是否存在NULL值;
2. 對NOT IN運算如T1.C1 NOT IN (SELECT T2.C1 FROM T2) 時,如果表T2的C1列存在NULL值, 那么查詢將不會返回任何記錄,無論表T1的C1列是否有NULL值存在。
3. 對NOT EXISTS運算如NOT EXISTS(SELECT C1 FROM T2 WHERE T2.C1=T1.C1),會返回T1表有但T2表沒有且T1.C2 IS NOT NULL的記錄
測試DEMO
新聞熱點
疑難解答