做一個積極的人
編碼、改bug、提升自己
我有一個樂園,面向編程,春暖花開!
01 小木的故事
作為后台開發,在日常工作中如果要接觸Mysql數據庫,那么不可避免會遇到Mysql中的NULL和空值。那你知道它們有什么區別嗎?
學不動了,也不想知道它們有什么區別。大兄弟,不行啊,要面試!
前些天我的好朋友小木去應聘工作,他面試完回來和我聊天回味了一道他的面試題。
面試官:你有用過MySQL嗎?
小木:有!
面試官:那你能大概說一下Mysql中 NULL值和空值的區別嗎?
小木:(思考…)NULL和空值都用過,你要我說它兩有啥區別,這個我還真沒仔細想過,反正實際開發中會用!
聽了小木的這個回答。
我說:你這樣回答肯定是不妥的,這個問題你是必掛了。
小木說: NULL翻譯過來不就是空嗎?我是真的沒有仔細想過,這個還是挺迷惑人的。
為了其他的伙伴在遇到這個問題的時候不要像我的好友小木一樣在此處跌倒,錯過心儀的公司,下面簡單整理聊聊這兩者的一些區別和使用。
02 NULL和空值
NULL也就是在字段中存儲NULL值,空值也就是字段中存儲空字符('')。
1、占用空間區別
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值就是一個裝滿空氣的杯子,雖然看起來都是一樣的,但是有着本質的區別。
2、插入/查詢方式區別
創建一個表,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查詢,而空值('')可以使用=或者!=、<、>等算術運算符。
3、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
函數返回第二個參數的值(默認值)。
4、索引字段說明
看到網上有一些人說: MySql中如果某一列中含有NULL,那么包含該列的索引就無效了。
給one
和two
字段分別加上普通索引。之前有寫過,在復習添加索引: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 總結提升
如果你可以從上面的幾個方面和面試官進行一個溝通,即使回答的不是那么的完美,但總比 “這兩個都用過,具體有啥區別就不知道了” 這樣的回答能好那么一點點。
1、空值不占空間,NULL值占空間。當字段不為NULL時,也可以插入空值。
2、當使用 IS NOT NULL 或者 IS NULL 時,只能查出字段中沒有不為NULL的或者為 NULL 的,不能查出空值。
3、判斷NULL 用IS NULL 或者 is not null,SQL 語句函數中可以使用IFNULL()函數來進行處理,判斷空字符用 =''或者<>''來進行處理。
4、在進行count()統計某列的記錄數的時候,如果采用的NULL值,會別系統自動忽略掉,但是空值是會進行統計到其中的。
5、MySql中如果某一列中含有NULL,那么包含該列的索引就無效了。這一句不是很准確。
6:實際到底是使用NULL值還是空值(''),根據實際業務來進行區分。個人建議在實際開發中如果沒有特殊的業務場景,可以直接使用空值。
以上就是我的對此問題的整理和思考,希望可以在面試中幫助到你。如果你對此話題有自己的思考和理解,也歡迎留言一起探討!
04 參考資料
https://www.cnblogs.com/wzmenjoy/p/4244590.html
https://dev.mysql.com/doc/refman/5.7/en/working-with-null.html
謝謝你的閱讀,如果您覺得這篇博文對你有幫助,請點贊或者喜歡,讓更多的人看到!祝你每天開心愉快!
不管做什么,只要堅持下去就會看到不一樣!在路上,不卑不亢!
願你我在人生的路上能都變成最好的自己,能夠成為一個獨擋一面的人
© 每天都在變得更好的阿飛雲