Stop MySQL tolerating multiple NULLs in a UNIQUE constraint

[亡魂溺海] 提交于 2019-12-01 16:02:24

Warning: This answer is outdated. As of MySQL 5.1, BDB is not supported.

It depends on MySQL Engine Type. BDB doesn't allow multiple NULL values using UNIQUE but MyISAM and InnoDB allows multiple NULLs even with UNIQUE.

In general, depending on the storage engine, NULL may or may not be seen as a unique value. You must be using a storage engine which doesn't recognise NULL as a unique value, eg. InnoDB or MyISAM.

To get around this you can create a "null value", such as 99999999, which you can recognise as NULL as there is no way to change how your storage engine decides to deal with nulls in unique keys.

UPDATE: You should use the idea suggested by @greenoldman in the comment below instead. Create a boolean field with triggers to set the value based on whether your nullable field is NULL or not and then combine the boolean field in a unique constraint with the other fields that define uniqueness.


I found a way around this problem if you must enforce the unique constraint but also need to have a foreign key on the column, thus requiring it to be nullable. My solution was derived from this and will require a little extra space. This is an example with a numeric id field.

The basic concept is that you have to create another non-nullable field that will have the value of your nullable field with the foreign key duplicated into it with a trigger. The unique constraint will then be enforced on the non-nullable duplicate field. To do this you need to define a non-nullable field with a default value of 0 similar to this:

ALTER TABLE `my_table` ADD  `uniq_foo` int(10) UNSIGNED NOT NULL DEFAULT '0';

Then you just have to define some triggers like this:

DROP TRIGGER IF EXISTS `my_table_before_insert`;
DELIMITER ;;
CREATE TRIGGER `my_table_before_insert` BEFORE INSERT ON `my_table`
FOR EACH ROW
BEGIN
    SET NEW.uniq_foo = IFNULL(NEW.foo_id, 0);
END;;
DELIMITER ;

DROP TRIGGER IF EXISTS `my_table_before_update`;
DELIMITER ;;
CREATE TRIGGER `my_table_before_update` BEFORE UPDATE ON `my_table`
FOR EACH ROW
BEGIN
    SET NEW.uniq_foo = IFNULL(NEW.foo_id, 0);
END;;
DELIMITER ;

BDB doesn't allow multiple NULL values using UNIQUE. But MySQL drop the BDB engine (http://dev.mysql.com/doc/relnotes/mysql/5.1/en/news-5-1-12.html).

So now : http://dev.mysql.com/doc/refman/5.5/en/create-index.html

For all engines, a UNIQUE index permits multiple NULL values for columns that can contain NULL. If you specify a prefix value for a column in a UNIQUE index, the column values must be unique within the prefix.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!