不再迷惑,無值和 NULL 值

發表於2017-06-21

在關係型資料庫的世界中,無值和NULL值的區別是什麼?一直被這個問題困擾著,甚至在寫TSQL指令碼時,心有慼慼焉,害怕因為自己的一知半解,挖了坑,貽害後來人,於是,本著上下求索,不達通幽不罷休的決心(開個玩笑),遂有此文。

學習過關係型資料庫的夥伴都知道,NULL是指不確定的值,在資料庫中絕對是噩夢的存在;而空值,一般對字串型別而言,指沒有任何值的字串型別,為字元型別的變數設定為空值:set @vs=”,空值跟無值不同。有人可能會問,無值是什麼?無值,是指資料表中沒有任何資料。無值和不確定值,單從字面意思上來看,兩者之間的定義很清楚,一旦深究,這兩者之間的關係,有時令人十分迷惑(confused),這是因為,在特定條件下,無值會轉換為NULL值。

一,舉個例子,理解無值和NULL值的區別

比如,建立一個臨時表,在不插入任何資料時,該資料表是空的,沒有任何值,對其執行select命令,將不會返回任何資料值:

建立一個標量型別的變數,在不初始化時,該變數的值是不確定的,其值是NULL:

建立一個表型別變數,在不初始化時,該表變數沒有任何資料,是無值的:

總結一下,宣告一個標量型變數,如果沒有對變數進行初始化,其值是不確定的,是NULL值;對於表變數,臨時表和基礎表,如果沒有插入任何資料,該表沒有任何資料,是無值的。

二,無值和NULL值的轉換

在開始本節之前,先為變數賦值,簡單的一個select命令就可以完成變數的賦值:

有些朋友思維比較活躍,立馬會想到:“用select命令可以從表中取值為變數賦值”,對,但是,賦值方法不是我求索的重點,我關注的是從表中取值為變數賦值的結果。

1,從空表中為變數賦值

如果資料表是空表,沒有任何值,那麼資料庫引擎不會執行賦值語句,變數保持原有值不變:

但是,如果採用以下方式,那麼資料庫引擎會執行賦值語句,由於空表不返回任何值,資料庫引擎會把無值轉換為不確定值NULL:

詫異嗎?無值和NULL值的轉換,居然從不起眼的變數賦值開始。注意,當不返回任何值時,資料庫引擎不確定返回值,就把無值轉換為NULL值。

2,從空表中計算聚合

空表是沒有任何資料的表,計算聚合會產生怎樣的結果?

當統計資料行數時,返回的是0;當計算聚合函式(max,min,avg和sum)的聚合值時,由於無值可以聚合,資料庫引擎不能確定這些聚合函式的返回值,因此,資料庫引擎返回NULL值。

628084-20170620110230601-1550885802

三,聚合函式忽略NULL值

一般情況下,除了count(0),count(*)之外,聚合函式都會忽略NULL值,而統計非NULL值,如果讀者有疑問,可以檢視我的部落格《TSQL 聚合函式忽略NULL值》。如果只知聚合函式忽略NULL值,而不知空表也會產生結果為NULL的聚合值,輕易得出聚合函式不會返回NULL值的定論,那就很尷尬。樓主曾遇到過一次“意外”,在一次除錯指令碼程式碼的過程中,我遇到max聚合函式返回NULL值的情況,當時一臉懵逼,直接懷疑自己之前的所學。

當聚合列值都是NULL值時,由於聚合函式忽略NULL值,因此,當計算聚合函式(max,min,avg和sum)的聚合值時,由於無值可以聚合,資料庫引擎不能確定這些聚合函式的返回值,因此,資料庫引擎返回NULL值。

聚合函式(max,min,sum,avg和count)忽略null值,但不代表聚合函式不返回null值:如果資料表為空表,或聚合列值都是null,那麼max,min,sum,avg聚合函式返回null值,而count 聚合函式返回0。聚合函式的共性:Null values are ignored。

628084-20170620112538616-1090159798

不再迷惑:當不返回任何值時,資料庫引擎不確定返回值,就把無值轉換為NULL值。

相關文章