My SQL schema is
CREATE TABLE Foo (
`bar` INT NULL ,
`name` VARCHAR (59) NOT NULL ,
UNIQUE ( `name`, `bar` )
) ENGINE = INNODB;
MySQL is allowing the following statement to be repeated, resulting in duplicates.
INSERT INTO Foo (`bar`, `name`) VALUES (NULL, 'abc');
despite having
UNIQUE ( `name`, `bar` )
Why is this tolerated and how do I stop it?
Unique key constraints can accept only one NULL value for column. Unique constraints are also referenced by the foreign key of another table.
You can insert NULL values into columns with the UNIQUE constraint because NULL is the absence of a value, so it is never equal to other NULL values and not considered a duplicate value. This means that it's possible to insert rows that appear to be duplicates if one of the values is NULL .
Another difference is that the UNIQUE constraint allows for one NULL value, but the PRIMARY KEY does not allow NULL values.
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 NULL
s 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 ;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With