我正在尋找如何使用NULL檢查來實現唯一約束。如何使用唯一約束在MySQL中使用NULL值
MySQL不應該允許多個空值。
員工:
id | name
---|-----
1 | null
2 | null -> should give error during inserting 2nd row.
我正在尋找如何使用NULL檢查來實現唯一約束。如何使用唯一約束在MySQL中使用NULL值
MySQL不應該允許多個空值。
員工:
id | name
---|-----
1 | null
2 | null -> should give error during inserting 2nd row.
不,MySQL是做正確的事,根據SQL-99規範。
https://mariadb.com/kb/en/sql-99/constraint_type-unique-constraint/
的唯一約束使得它不可能犯任何的操作, 會導致唯一鍵包含任何非空重複的值。 (多允許空值,因爲空值永遠不會等於 到任何東西,甚至是另一個空值。)
如果你使用一個唯一的約束,但不希望與空多行後,宣佈該列作爲NOT NULL
並禁止任何行具有NULL。
的MySQL 5.7確實允許一個解決辦法:
mysql> CREATE TABLE `null_test` (
-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-> `const` varchar(255) NOT NULL DEFAULT '',
-> `deleted_at` datetime DEFAULT NULL,
-> PRIMARY KEY (`id`)
->) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.03 sec)
隨着軟刪除,這將是很好,如果你可以只有一個有一排用deleted_at = NULL
每約束。
mysql> ALTER TABLE `null_test` ADD `vconst` int(1) GENERATED ALWAYS AS (((NULL = `deleted_at`) or (NULL <=> `deleted_at`))) VIRTUAL;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
所以我創建了一個虛擬列將從1
翻轉null
時deleted_at
被設定。
mysql> ALTER TABLE `null_test` ADD UNIQUE KEY `nullable_index` (`const`,`vconst`);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
而是包括deleted_at
的唯一約束添加虛擬列,vconst
。不需要插入vconst
(但不能,無論如何)。
mysql> INSERT INTO `null_test` SET `const` = 'Ghost';
ERROR 1062 (23000): Duplicate entry 'Ghost-1' for key 'nullable_index'
再次插入會引發重複輸入錯誤。
mysql> UPDATE `null_test` SET `deleted_at` = NOW() WHERE `const` = 'Ghost';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
同樣的,設置delete_at
,無需觸摸vconst
,它會自動翻轉。
mysql> SELECT * FROM `null_test` WHERE `const` = 'Ghost';
+--------+-------+---------------------+--------+
| id | const | deleted_at | vconst |
+--------+-------+---------------------+--------+
| 999901 | Ghost | 2017-02-16 22:07:45 | NULL |
+--------+-------+---------------------+--------+
1 row in set (0.00 sec)
mysql> INSERT INTO `null_test` SET `const` = 'Ghost';
Query OK, 1 row affected (0.00 sec)
現在您可以自由插入具有相同約束的新行!
mysql> SELECT * FROM `null_test` WHERE `const` = 'Ghost';
+--------+-------+---------------------+--------+
| id | const | deleted_at | vconst |
+--------+-------+---------------------+--------+
| 999901 | Ghost | 2017-02-16 22:07:45 | NULL |
| 999903 | Ghost | NULL | 1 |
+--------+-------+---------------------+--------+
2 rows in set (0.01 sec)
在這種情況下,這取決於你的軟多少刪除,設置deleted_at
,你可能要包括deleted_at
到索引,或者用一個新的索引,但我會讓負載測試決定。
你能分享一下你得到的錯誤嗎? – Sadikhasan
我在問如何實現它。現在它將多個null插入到數據庫中 –