---
tags: Database
---
# SQL 中的 `NULL`
* `NULL` 代表了遺失、未知或是不適用。
> Generally, you use the NULL value to indicate that the **data is missing, unknown, or not applicable**.
>
> [name=[MySQL NULL / MySQL TUTORIAL](http://www.mysqltutorial.org/mysql-null/)]
而數值零或空字串值,這兩者都表示已知的值,並不等於是 `NULL`。
> 幾個情境示範:
>
> ```
> | Name | Phone |
> |---------|--------------|
> | Celine | '0987654321' | 有電話
> | Antonio | '' | 他真的沒電話
> | Gary | NULL | 不知道他有沒有電話
> | Doggy | NULL | 狗不會有電話
> ```
> [color=lightblue]
* `NULL` 不會等於任何其他東西,因為 `NULL` 是未知的,它可以是任何值。
> **A `NULL` value is not equal to anything, even itself.** If you compare a `NULL` value with another `NULL` value or any other value, the result is `NULL` because the value of each `NULL` value is unknown.
>
> [name=[MySQL NULL / MySQL TUTORIAL](http://www.mysqltutorial.org/mysql-null/)]
`NULL` 不會等於另一個 `NULL`,所以搜尋 `value = NULL` 是不會有結果的。
```sql
SELECT * FROM `user` WHERE `phone` = NULL; ✖︎
⬇
SELECT * FROM `user` WHERE `phone` IS NULL; ✔︎
```
另外 `NULL` 也可以被用在 Unique key,MySQL 會將其視為不同的值。
> 假設現在有一組 Unique key `btree__name__address` ,接下來新增兩筆資料。
>
> ```sql
> INSERT INTO `user` (`name`, `address`) VALUES
> ('Antonio', NULL),
> ('Antonio', NULL);
> ```
>
> 以上狀況是可以成功新增的,因為 Antonio ~~搞不好家財萬貫~~,就是有這麼多棟房子,只是我們不知道在哪而已。
> [color=lightblue]
* SQL 使用了[三值邏輯 three-valued logic](https://zh.wikipedia.org/wiki/%E4%B8%89%E5%80%BC%E9%80%BB%E8%BE%91),以 `NULL` 代表 unkown。
 哇母災


> 可以用有沒有吃飽來當情境想像,列幾項例子,以此類推:
> * `True AND True` :我吃飽你也吃飽,我們都吃飽 → `True`
> * `True AND Unkown` :我吃飽你不知道有沒有吃飽,我們不一定都吃飽 → `Unkown`
> * `True AND False` :我吃飽你沒吃飽,我們沒有都吃飽 → `False`
> * `True OR Unkown`:我吃飽你不知道有沒有吃飽,我們其中一個人有吃飽 → `True`
>
> [color=lightblue]
> 幾個 `IN` 的比較:
> ```sql
> SELECT 1 IN (1, NULL); -- return True
> SELECT 1 NOT IN (1, NULL); -- return False
>
> SELECT 2 IN (1, NULL); -- return NULL
> SELECT 2 NOT IN (1, NULL); -- return NULL
>
> SELECT NULL IN (1, NULL); -- return NULL
> SELECT NULL NOT IN (1, NULL); -- return NULL
> -- NULL 可以是任何值,不一定會與後方的 NULL 相同,所以是 NULL
> ```
> [color=lightblue]
* 與數學運算符結果的結果永遠是 unknown。
 不知道就是不知道,算再久還是不知道。
## Function
### [`ISNULL`](http://www.mysqltutorial.org/mysql-isnull-function/)
如果參數是 `NULL` 就回傳 `1`,否則回傳 `0`。
```sql
SELECT ISNULL(NULL); -- 1
SELECT ISNULL(1); -- 0
SELECT ISNULL(1 + NULL); -- 1
SELECT ISNULL(1 / 0); -- 1
```
> If a `DATE` or `DATETIME` column that has a `NOT NULL` constraint and contains a special date `'0000-00-00'`, you can use the `IS NULL` operator to find such rows.
>
> [name=[MySQL IS NULL / MySQL TUTORIAL](http://www.mysqltutorial.org/mysql-is-null/)]
### [`IFNULL`](http://www.mysqltutorial.org/mysql-ifnull/)
接受兩個 arguments,如果第一個參數不是 `NULL` 就回傳,如果是 `NULL` 則回傳第二個參數。
```sql
SELECT IFNULL(1, 'N/A'); -- returns 1
SELECT IFNULL('', 'N/A'); -- returns ''
SELECT IFNULL(NULL, 'N/A'); -- returns 'N/A'
```
### [`NULLIF`](http://www.mysqltutorial.org/mysql-nullif/)
接受兩個 arguments,如果相同就回傳 `NULL`,否則回傳第一個參數。
> 情境可以搭配 `COALESCE` 使用,我們希望出來的優先聯絡資訊是有值的,而空字串也代表有值,並非我們預期的結果,因此可以加上 `NULLIF` 修改。:
>
> ```sql
> INSERT INTO `user` (`name`, `phone`, `email`) VALUES
> ('Celine', '', 'celine@mail');
>
> SELECT `name`, COALESCE(
> `phone`, `email`
> ) `contact` FROM `user`;
>
> | name | contact |
> |--------|---------|
> | Celine | '' |
>
> ⬇
>
> SELECT `name`, COALESCE(
> NULLIF(`phone`, ''),
> NULLIF(`email`, '')
> ) `contact` FROM `user`;
>
> | name | contact |
> |--------|-------------|
> | Celine | celine@mail |
> ```
>
>
>
> [color=lightblue]
### [`COALESCE`](http://www.mysqltutorial.org/mysql-coalesce/)
接受一連串的 arguments,回傳第一個非 `NULL` 的值。
## [Comparison with null](https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to)
> NULL-safe equal. This operator performs an equality comparison like the = operator, but returns 1 rather than NULL if both operands are NULL, and 0 rather than NULL if one operand is NULL.
```
1 <=> 1 # 1
null <=> null # 1
null <=> 1 # 0
1 <=> 2. # 0
```
## 參考資料
* [The Three-Valued Logic of SQL / Modern SQL](https://modern-sql.com/concept/three-valued-logic)
* [MySQL NULL / MySQL TUTORIAL](http://www.mysqltutorial.org/mysql-null/)