MySQL中有唯一索引的設(shè)計(jì),常常使用在需要唯一性的列上面,例如用戶名、郵箱等等。通常,當(dāng)我們?cè)趧?chuàng)建唯一索引時(shí),如果插入一行數(shù)據(jù)時(shí)出現(xiàn)重復(fù),MySQL會(huì)拋出Duplicate Key錯(cuò)誤,但實(shí)際上,我們可以使用NULL作為唯一索引,且該行數(shù)據(jù)可以成功插入。
為什么會(huì)出現(xiàn)這種情況呢?這是由于在MySQL的索引結(jié)構(gòu)中,NULL值在B-Tree索引結(jié)構(gòu)中只會(huì)在葉節(jié)點(diǎn)中出現(xiàn),而且B-Tree索引中的葉節(jié)點(diǎn)以及非葉節(jié)點(diǎn)都是按照順序排列的。這就導(dǎo)致了一個(gè)問題:NULL值視為無限小,可以排到索引結(jié)構(gòu)的最前面。
下面,我們來看一下代碼例子:
CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) DEFAULT NULL, UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB; INSERT INTO `test` (`id`, `name`) VALUES (1, NULL); INSERT INTO `test` (`id`, `name`) VALUES (2, NULL); INSERT INTO `test` (`id`, `name`) VALUES (3, 'Tom');
上述代碼創(chuàng)建了一個(gè)表test,其中name列有唯一索引??梢园l(fā)現(xiàn),在插入id為1和2的數(shù)據(jù)時(shí),name被賦了NULL值,但依然可以成功插入到表中。因此,當(dāng)讀取數(shù)據(jù)時(shí),需要注意,在檢查唯一索引的時(shí)候就要特別處理NULL值的情況。
最后,需要注意的是,雖然在MySQL中使用NULL值可以讓唯一索引走null,但是在實(shí)際的數(shù)據(jù)庫(kù)設(shè)計(jì)中并不推薦這么使用。因?yàn)镹ULL值的處理會(huì)增加數(shù)據(jù)的復(fù)雜性,同時(shí)也會(huì)影響查詢性能。因此,在實(shí)際應(yīng)用中,建議將該列設(shè)置為NOT NULL并使用默認(rèn)值。