【面試】MySQL 中NULL和空值的區別?

作一個積極的人html

編碼、改bug、提高本身mysql

我有一個樂園,面向編程,春暖花開!面試

01 小木的故事

做爲後臺開發,在平常工做中若是要接觸Mysql數據庫,那麼不可避免會遇到Mysql中的NULL和空值。那你知道它們有什麼區別嗎?sql

學不動了,也不想知道它們有什麼區別。大兄弟,不行啊,要面試!數據庫

前些天個人好朋友小木去應聘工做,他面試完回來和我聊天回味了一道他的面試題。編程


面試官:你有用過MySQL嗎?函數

小木:有!ui

面試官:那你能大概說一下Mysql中 NULL值和空值的區別嗎?編碼

小木:(思考...)NULL和空值都用過,你要我說它兩有啥區別,這個我還真沒仔細想過,反正實際開發中會用!spa

聽了小木的這個回答。

我說:你這樣回答確定是不妥的,這個問題你是必掛了。

小木說: NULL翻譯過來不就是空嗎?我是真的沒有仔細想過,這個仍是挺迷惑人的。


爲了其餘的夥伴在遇到這個問題的時候不要像個人好友小木同樣在此處跌倒,錯過心儀的公司,下面簡單整理聊聊這二者的一些區別和使用。

02 NULL和空值

NULL也就是在字段中存儲NULL值,空值也就是字段中存儲空字符('')。

一、佔用空間區別

mysql>  select length(NULL), length(''), length('1');
+--------------+------------+-------------+
| length(NULL) | length('') | length('1') |
+--------------+------------+-------------+
| NULL         |          0 |           1 |
+--------------+------------+-------------+
1 row in set
複製代碼

小總結:從上面看出空值('')的長度是0,是不佔用空間的;而的NULL長度是NULL,其實它是佔用空間的,看下面說明。

NULL columns require additional space in the row to record whether their values are NULL.

NULL列須要行中的額外空間來記錄它們的值是否爲NULL。

通俗的講:空值就像是一個真空轉態杯子,什麼都沒有,而NULL值就是一個裝滿空氣的杯子,雖然看起來都是同樣的,可是有着本質的區別。

二、插入/查詢方式區別

建立一個表,tb_test

CREATE TABLE `tb_test` (
  `one` varchar(10) NOT NULL,
  `two` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
複製代碼

插入進行驗證:

-- 所有插入 NULL,失敗
mysql> INSERT tb_test VALUES (NULL,NULL);
1048 - Column 'one' cannot be null
複製代碼
-- 所有插入 空值,成功
mysql> INSERT tb_test VALUES ('','');
Query OK, 1 row affected
複製代碼

模擬數據:

INSERT tb_test VALUES (1,NULL);
INSERT tb_test VALUES ('',2);
INSERT tb_test VALUES (3,3);
複製代碼

空值字段:

-- 使用 is null/is not null
mysql> SELECT * FROM tb_test where one is NULL;
Empty set

mysql> SELECT * FROM tb_test where one is not NULL;
+-----+------+
| one | two  |
+-----+------+
| 1   | NULL |
|     | 2    |
| 3   | 3    |
+-----+------+
3 rows in set
-- 使用 = 、!=
mysql> SELECT * FROM tb_test where one = '';
+-----+-----+
| one | two |
+-----+-----+
|     | 2   |
+-----+-----+
1 row in set

mysql> SELECT * FROM tb_test where one != '';
+-----+------+
| one | two  |
+-----+------+
| 1   | NULL |
| 3   | 3    |
+-----+------+
2 rows in set

複製代碼

NULL值字段:

-- 使用 is null/is not null
mysql> SELECT * FROM tb_test where two is not NULL;
+-----+-----+
| one | two |
+-----+-----+
|     | 2   |
| 3   | 3   |
+-----+-----+
2 rows in set

mysql> SELECT * FROM tb_test where two is NULL;
+-----+------+
| one | two  |
+-----+------+
| 1   | NULL |
+-----+------+
1 row in set

-- 使用 = 、!=
mysql> SELECT * FROM tb_test where two = '';
Empty set

mysql> SELECT * FROM tb_test where two != '';
+-----+-----+
| one | two |
+-----+-----+
|     | 2   |
| 3   | 3   |
+-----+-----+
2 rows in set
複製代碼

小總結:若是要單純查NULL值列,則使用 is NULL去查,單純去查空值('')列,則使用 =''

建議查詢方式:NULL值查詢使用is null/is not null查詢,而空值('')可使用=或者!=、<、>等算術運算符。

三、COUNT 和 IFNULL函數

使用COUNT函數:

mysql> SELECT count(one) FROM tb_test;
+------------+
| count(one) |
+------------+
|          3 |
+------------+
1 row in set

mysql> SELECT count(two) FROM tb_test;
+------------+
| count(two) |
+------------+
|          2 |
+------------+
1 row in set

mysql> SELECT count(*) FROM tb_test;
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set
複製代碼

使用IFNULL函數:

mysql> SELECT IFNULL(one,111111111) from tb_test WHERE one = '';
+-----------------------+
| IFNULL(one,111111111) |
+-----------------------+
|                       |
+-----------------------+
1 row in set

mysql> SELECT IFNULL(two,11111111) from tb_test where two is NULL;
+----------------------+
| IFNULL(two,11111111) |
+----------------------+
| 11111111             |
+----------------------+
1 row in set
複製代碼

小總結:使用 COUNT(字段) 統計會過濾掉 NULL 值,可是不會過濾掉空值。

說明:IFNULL有兩個參數。 若是第一個參數字段不是NULL,則返回第一個字段的值。 不然,IFNULL函數返回第二個參數的值(默認值)。

四、索引字段說明

看到網上有一些人說: MySql中若是某一列中含有NULL,那麼包含該列的索引就無效了。

onetwo 字段分別加上普通索引。以前有寫過,在複習添加索引:Mysql索引整理總結

-- ALTER TABLE table_name ADD INDEX index_name(col_name);
ALTER TABLE tb_test ADD INDEX index_oat (one, two);
ALTER TABLE tb_test add INDEX index_two(two);
複製代碼

使用 show keys from 表名;show indexes from 表名; ,查看這個表的全部索引信息。

一個普通索引,一個複合索引。

複合索引遵照「最左前綴」原則即在查詢條件中使用了複合索引的第一個字段,索引纔會被使用。所以,在複合索引中索引列的順序相當重要。

能夠看到,建立了兩個索引,而且index_tow NULL 那一列是 YES。

使用EXPLAIN 來進行演示說明,EXPLAIN 的使用說明:Mysql中explain用法和結果字段的含義介紹

複合索引

普通索引

發現查詢two字段 是能夠正常使用索引的。我使用的MYSQL 5.7 ,InnoDB 引擎。也看了一些網上的資料,MySQL中NULL對索引的影響 這個文章中用例子驗證,MySQL能夠在含有null的列上使用索引

備註:多是其餘條件下不行,看網上資料說使用空間索引會失效,具體我沒有去驗證,空間索引沒有用到過。查詢官網create-index-spatial,感興趣的夥伴能夠自行驗證。

這裏我想到一點,不少問題的答案都是在指定的條件和環境下才成立,多質疑,多驗證。

小總結 :在有NULL值得字段上使用經常使用的索引,如普通索引、複合索引、全文索引等不會使索引失效。在官網查看在空間索引的狀況下,說明了 索引列必須爲NOT NULL。

03 總結提高

若是你能夠從上面的幾個方面和麪試官進行一個溝通,即便回答的不是那麼的完美,但總比 「這兩個都用過,具體有啥區別就不知道了」 這樣的回答能好那麼一點點。

一、空值不佔空間,NULL值佔空間。當字段不爲NULL時,也能夠插入空值。

二、當使用 IS NOT NULL 或者 IS NULL 時,只能查出字段中沒有不爲NULL的或者爲 NULL 的,不能查出空值。

三、判斷NULL 用IS NULL 或者 is not null,SQL 語句函數中可使用IFNULL()函數來進行處理,判斷空字符用 =''或者<>''來進行處理。

四、在進行count()統計某列的記錄數的時候,若是採用的NULL值,會別系統自動忽略掉,可是空值是會進行統計到其中的。

五、MySql中若是某一列中含有NULL,那麼包含該列的索引就無效了。這一句不是很準確。

6:實際究竟是使用NULL值仍是空值(''),根據實際業務來進行區分。我的建議在實際開發中若是沒有特殊的業務場景,能夠直接使用空值。

以上就是個人對此問題的整理和思考,但願能夠在面試中幫助到你。若是你對此話題有本身的思考和理解,也歡迎留言一塊兒探討!

04 參考資料

www.cnblogs.com/wzmenjoy/p/…

dev.mysql.com/doc/refman/…


謝謝你的閱讀,若是您以爲這篇博文對你有幫助,請點贊或者喜歡,讓更多的人看到!祝你天天開心愉快!



無論作什麼,只要堅持下去就會看到不同!在路上,不卑不亢!

願你我在人生的路上能都變成最好的本身,可以成爲一個獨擋一面的人

© 天天都在變得更好的阿飛雲

相關文章
相關標籤/搜索