MySQL:唯一索引不符合 `null` 值

标签 mysql constraints

我在 MySQL v5.6.20 中创建关于 null 值的唯一索引时遇到问题。我在这里检查了类似的答案。但无法解决我的问题。

期望的行为

我想要一个引用了其他三个表 (date_list_assignment) 的表。该表的目的是将 date_list 条目映射到类(class)类别和/或 date_list 类别。因此,第一列是强制性的,而后两列不是。如果后两者为 null,则日期列表条目被声明为全局。如果日期列表条目在此表中没有条目,则不会在任何地方显示。

以下是条目及其含义的一些示例:

# entry which is global within course category 2
date_list_id: 1, course_category_id: 2, date_list_category_id: null

# entry which is global
date_list_id: 1, course_category_id: null, date_list_category_id: null

# entry which is only visible within course category 2 and date list category 17
date_list_id: 1, course_category_id: 2, date_list_category_id: 17

简短版本:我想确保三列的任意组合在表中保持唯一...无论值是否为空。

表架构

我有下表:

CREATE TABLE `date_list_assignment` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `date_list_id` int(11) NOT NULL,
  `course_category_id` int(11) DEFAULT NULL,
  `date_list_category_id` int(11) DEFAULT NULL,
  `created` int(11) DEFAULT NULL,
  `created_by` int(11) DEFAULT NULL,
  `updated` int(11) DEFAULT NULL,
  `updated_by` int(11) DEFAULT NULL,

  PRIMARY KEY (`id`),
  UNIQUE KEY `IN_relation_unique` (`date_list_id`,`course_category_id`,`date_list_category_id`),

  KEY `FK_date_list_assignment_user_created` (`created_by`),
  KEY `FK_date_list_assignment_user_updated` (`updated_by`),
  KEY `FK_date_list_assignment_course_category` (`course_category_id`),
  KEY `FK_date_list_assignment_date_list_category` (`date_list_category_id`),

  CONSTRAINT `FK_date_list_assignment_course_category` FOREIGN KEY (`course_category_id`) REFERENCES `course_category` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `FK_date_list_assignment_date_list` FOREIGN KEY (`date_list_id`) REFERENCES `date_list` (`id`) ON UPDATE CASCADE,
  CONSTRAINT `FK_date_list_assignment_date_list_category` FOREIGN KEY (`date_list_category_id`) REFERENCES `date_list_category` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `FK_date_list_assignment_user_created` FOREIGN KEY (`created_by`) REFERENCES `user` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `FK_date_list_assignment_user_updated` FOREIGN KEY (`updated_by`) REFERENCES `user` (`id`) ON DELETE SET NULL ON UPDATE CASCADE

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

问题

如您所见,我在三列上声明了一个唯一索引 (IN_relation_unique)。但是,我仍然可以创建具有例如这些值的相同行:

date_list_id: 1, course_category_id: 2, date_list_category_id: null

我知道某些行为在当前的 MySQL 版本中发生了变化,这也是我使用索引而不是允许空值的复合 PK 的原因。

例如this answer指出,这是 MySQL 中的预期行为。如果是这样,您如何实现这一目标,因为它也不再可能使用允许空值的复合 PK!?

感谢您的帮助!

最佳答案

是的,这是 MySQL 中的预期行为(实际上在 ANSI-92 中也是如此)。 NULL 值在唯一键中不被视为相等值,并且根据定义,主键不能包含 NULL 值。

A unique constraint is satisfied if and only if no two rows in a table have the same non-null values in the unique columns. In addition, if the unique constraint was defined with PRIMARY KEY, then it requires that none of the values in the specified column or columns be the null value.

( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt )

由于您在可空列上有外键约束,我建议向父表添加一个虚拟值,说明父表不相关或未确定的事实(可能是 ID = 0 的记录)并添加列的 NOT NULL 约束。 (此外,您可以将虚拟值添加为 DEFAULT)。

关于MySQL:唯一索引不符合 `null` 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36328844/

相关文章:

c# - 如何在 LINQ 中使用 ToString() 方法将整数转换为字符串

Mysql 乘法计数

mysql - 无法远程连接到 MySQL

iphone - 向 UITableVIew headerview 添加约束

php - UNIX_TIMESTAMP(时间戳) 使用

c# - 中等信任共享环境上的 MySql Connectors 6.7.4

c# - 在通用类中同时具有 "class"和 "new()"约束是否毫无意义?

ios - 通过自动布局根据 UILabel 的内容自动调整 UIView 的大小

ios - UIImageView 约束为 1 :1 aspect ratio and 1:1 scaled to original?

java - 从 JRuby 调用 Java 方法会抛出 "no constructor for arguments error"