mysql两个字段相减_MySQL 中NULL和空值的区别?
作為后臺(tái)開發(fā),在日常工作中如果要接觸Mysql數(shù)據(jù)庫(kù),那么不可避免會(huì)遇到Mysql中的NULL和空值。那你知道它們有什么區(qū)別嗎?
學(xué)不動(dòng)了,也不想知道它們有什么區(qū)別。大兄弟,不行啊,要面試!
前些天我的好朋友小木去應(yīng)聘工作,他面試完回來(lái)和我聊天回味了一道他的面試題。
面試官:你有用過(guò)MySQL嗎?
小木:有!
面試官:那你能大概說(shuō)一下Mysql中 NULL值和空值的區(qū)別嗎?
小木:(思考…)NULL和空值都用過(guò),你要我說(shuō)它兩有啥區(qū)別,這個(gè)我還真沒(méi)仔細(xì)想過(guò),反正實(shí)際開發(fā)中會(huì)用!
聽了小木的這個(gè)回答。
我說(shuō):你這樣回答肯定是不妥的,這個(gè)問(wèn)題你是必掛了。
小木說(shuō): NULL翻譯過(guò)來(lái)不就是空嗎?我是真的沒(méi)有仔細(xì)想過(guò),這個(gè)還是挺迷惑人的。
為了其他的伙伴在遇到這個(gè)問(wèn)題的時(shí)候不要像我的好友小木一樣在此處跌倒,錯(cuò)過(guò)心儀的公司,下面簡(jiǎn)單整理聊聊這兩者的一些區(qū)別和使用。
02 NULL和空值
NULL也就是在字段中存儲(chǔ)NULL值,空值也就是字段中存儲(chǔ)空字符(’’)。
1、占用空間區(qū)別
mysql> select length(NULL), length(''), length('1');
+--------------+------------+-------------+
| length(NULL) | length('') | length('1') |
+--------------+------------+-------------+
| NULL | 0 | 1 |
+--------------+------------+-------------+
1 row in set
小總結(jié):從上面看出空值(’’)的長(zhǎng)度是0,是不占用空間的;而的NULL長(zhǎng)度是NULL,其實(shí)它是占用空間的,看下面說(shuō)明。
NULL columns require additional space in the row to record whether their values are NULL.
NULL列需要行中的額外空間來(lái)記錄它們的值是否為NULL。
通俗的講:空值就像是一個(gè)真空轉(zhuǎn)態(tài)杯子,什么都沒(méi)有,而NULL值就是一個(gè)裝滿空氣的杯子,雖然看起來(lái)都是一樣的,但是有著本質(zhì)的區(qū)別。
2、插入/查詢方式區(qū)別
創(chuàng)建一個(gè)表,tb_test
CREATE TABLE `tb_test` (
`one` varchar(10) NOT NULL,
`two` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入進(jìn)行驗(yàn)證:
-- 全部插入 NULL,失敗
mysql> INSERT tb_test VALUES (NULL,NULL);
1048 - Column 'one' cannot be null
-- 全部插入 空值,成功
mysql> INSERT tb_test VALUES ('','');
Query OK, 1 row affected
模擬數(shù)據(jù):
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
小總結(jié):如果要單純查NULL值列,則使用 is NULL去查,單純?nèi)ゲ榭罩?’’)列,則使用 =''。
建議查詢方式:NULL值查詢使用is null/is not null查詢,而空值(’’)可以使用=或者!=、等算術(shù)運(yùn)算符。
3、COUNT 和 IFNULL函數(shù)
使用COUNT函數(shù):
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函數(shù):
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
小總結(jié):使用 COUNT(字段) 統(tǒng)計(jì)會(huì)過(guò)濾掉 NULL 值,但是不會(huì)過(guò)濾掉空值。
說(shuō)明:IFNULL有兩個(gè)參數(shù)。 如果第一個(gè)參數(shù)字段不是NULL,則返回第一個(gè)字段的值。 否則,IFNULL函數(shù)返回第二個(gè)參數(shù)的值(默認(rèn)值)。
4、索引字段說(shuō)明
看到網(wǎng)上有一些人說(shuō): MySql中如果某一列中含有NULL,那么包含該列的索引就無(wú)效了。
給one 和two 字段分別加上普通索引。之前有寫過(guò),在復(fù)習(xí)添加索引:Mysql索引整理總結(jié)
-- 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 表名; ,查看這個(gè)表的所有索引信息。
一個(gè)普通索引,一個(gè)復(fù)合索引。
復(fù)合索引遵守“最左前綴”原則,即在查詢條件中使用了復(fù)合索引的第一個(gè)字段,索引才會(huì)被使用。因此,在復(fù)合索引中索引列的順序至關(guān)重要。
可以看到,創(chuàng)建了兩個(gè)索引,并且index_tow NULL 那一列是 YES。
使用EXPLAIN 來(lái)進(jìn)行演示說(shuō)明,EXPLAIN 的使用說(shuō)明:Mysql中explain用法和結(jié)果字段的含義介紹
復(fù)合索引
普通索引
發(fā)現(xiàn)查詢two字段 是可以正常使用索引的。我使用的MYSQL 5.7 ,InnoDB 引擎。也看了一些網(wǎng)上的資料,MySQL中NULL對(duì)索引的影響 這個(gè)文章中用例子驗(yàn)證,MySQL可以在含有null的列上使用索引。
備注:可能是其他條件下不行,看網(wǎng)上資料說(shuō)使用空間索引會(huì)失效,具體我沒(méi)有去驗(yàn)證,空間索引沒(méi)有用到過(guò)。查詢官網(wǎng)create-index-spatial,感興趣的伙伴可以自行驗(yàn)證。
這里我想到一點(diǎn),很多問(wèn)題的答案都是在指定的條件和環(huán)境下才成立,多質(zhì)疑,多驗(yàn)證。
小總結(jié) :在有NULL值得字段上使用常用的索引,如普通索引、復(fù)合索引、全文索引等不會(huì)使索引失效。在官網(wǎng)查看在空間索引的情況下,說(shuō)明了 索引列必須為NOT NULL。
03 總結(jié)提升
如果你可以從上面的幾個(gè)方面和面試官進(jìn)行一個(gè)溝通,即使回答的不是那么的完美,但總比 “這兩個(gè)都用過(guò),具體有啥區(qū)別就不知道了” 這樣的回答能好那么一點(diǎn)點(diǎn)。
1、空值不占空間,NULL值占空間。當(dāng)字段不為NULL時(shí),也可以插入空值。
2、當(dāng)使用 IS NOT NULL 或者 IS NULL 時(shí),只能查出字段中沒(méi)有不為NULL的或者為 NULL 的,不能查出空值。
3、判斷NULL 用IS NULL 或者 is not null,SQL 語(yǔ)句函數(shù)中可以使用IFNULL()函數(shù)來(lái)進(jìn)行處理,判斷空字符用 =’‘或者<>’'來(lái)進(jìn)行處理。
4、在進(jìn)行count()統(tǒng)計(jì)某列的記錄數(shù)的時(shí)候,如果采用的NULL值,會(huì)別系統(tǒng)自動(dòng)忽略掉,但是空值是會(huì)進(jìn)行統(tǒng)計(jì)到其中的。
5、MySql中如果某一列中含有NULL,那么包含該列的索引就無(wú)效了。這一句不是很準(zhǔn)確。
6:實(shí)際到底是使用NULL值還是空值(’’),根據(jù)實(shí)際業(yè)務(wù)來(lái)進(jìn)行區(qū)分。個(gè)人建議在實(shí)際開發(fā)中如果沒(méi)有特殊的業(yè)務(wù)場(chǎng)景,可以直接使用空值。
以上就是我的對(duì)此問(wèn)題的整理和思考。如果你對(duì)此話題有自己的思考和理解,也歡迎留言一起探討!也歡迎私信我探討交流哈,還有免費(fèi)的學(xué)習(xí)資料贈(zèng)送
總結(jié)
以上是生活随笔為你收集整理的mysql两个字段相减_MySQL 中NULL和空值的区别?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 微软 Bing Chat 已针对所有正式
- 下一篇: redis 发布订阅实际案例_【赵强老师