MySQL:不尊重“null”值的唯一索引

时间:2016-03-31 09:04:23

标签: mysql constraints

我无法在MySQL v5.6.20中创建一个尊重null - 值的唯一索引。我在这里查了类似的答案。但无法解决我的问题。

期望的行为

我想要一个引用另外三个表(date_list_assignment)的表。该表的目的是将date_list - 条目映射到课程类别和/或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的原因。

对于exmaple this answer状态,这是MySQL中的预期行为。如果是这样,你怎么能实现这一点,因为复合PK也不再允许空值!?

感谢您的帮助!

1 个答案:

答案 0 :(得分:6)

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

  

当且仅当表中没有两行在唯一列中具有相同的非空值时,才满足唯一约束。此外,如果使用PRIMARY KEY定义了唯一约束,则它要求指定列或列中的任何值都不是空值。

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

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