我有简单的分类表.类别可以有父类别(par_cat列)或空,如果它是主类别,并且具有相同的父类别,则不应该有两个或多个具有相同名称或url的类别.

此表的代码:

CREATE TABLE IF NOT EXISTS `categories` (
`id` int(10) unsigned NOT NULL,
  `par_cat` int(10) unsigned DEFAULT NULL,
  `lang` varchar(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'pl',
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `url` varchar(120) COLLATE utf8_unicode_ci NOT NULL,
  `active` tinyint(3) unsigned NOT NULL DEFAULT '1',
  `accepted` tinyint(3) unsigned NOT NULL DEFAULT '1',
  `priority` int(10) unsigned NOT NULL DEFAULT '1000',
  `entries` int(10) unsigned NOT NULL DEFAULT '0',
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;



ALTER TABLE `categories`
  ADD PRIMARY KEY (`id`), 
  ADD UNIQUE KEY `categories_name_par_cat_unique` (`name`,`par_cat`), 
  ADD UNIQUE KEY `categories_url_par_cat_unique` (`url`,`par_cat`), 
  ADD KEY `categories_par_cat_foreign` (`par_cat`);


ALTER TABLE `categories`
  MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3;

ALTER TABLE `categories`ADD CONSTRAINT `categories_par_cat_foreign` 
  FOREIGN KEY (`par_cat`) REFERENCES `categories` (`id`);

问题是,即使我有唯一的密钥,它也不起作用.如果我try 将两个par_cat设置为null且名称和url相同类别插入到数据库中,则这两个类别可以插入到数据库中而不会出现问题(而且它们不应该出现问题).但是,如果我为这些类别 Select 其他par_cat(例如,假设存在id为1的类别,则为1),则只插入第一条记录(这是所需的行为).

问题-如何处理这个案件?我读到:

唯一索引创建一个约束,以便索引中的所有值 必须是不同的.如果您try 添加具有以下属性的新行,则会发生错误 与现有行匹配的键值.此限制不适用 设置为空值,但BDB存储引擎除外.对于其他引擎, 唯一索引允许对可以包含以下内容的列使用多个NULL值 空.如果为唯一索引中列指定前缀值, 列值在前缀中必须是唯一的.

但是,如果我在多个列上具有UNIQUE,则情况并非如此(只有par_cat个可以为NULL,nameurl不能为NULL).因为par_cat个对同一表的id个引用,但是有些类别没有父类别,所以应该允许null个值.

推荐答案

这按照SQL标准的定义工作.NULL表示未知.如果您有两个记录par_cat=null和name=‘X’,则这两个NULL不会被视为具有相同的值.因此,它们不会违反唯一键约束.(嗯,有人可能会争辩说,NULL仍然表示相同的值,但是应用此规则将使得使用唯一索引和可为空的字段几乎是不可能的,因为NULL也可以表示1、2或任何其他值.因此,他们很好地定义了它,就像我认为的那样.)

由于MySQL不支持可以在ISNULL(par_cat,-1), name上建立索引的函数索引,因此如果希望约束起作用,您唯一的 Select 就是将par_cat设置为带有0或-1的非空列,或者用于"no parent"的任何值.

Database相关问答推荐

数据库是序列图中的控制器还是边界?

无法向 SiriDB 添加新副本

术语 SSTable 和 LSM Tree 有什么区别

Postgresql:优化数字字段的列大小

跨不同数据库创建视图

如何在 Windows 中安装 InfluxDB?

如果限制在本地机器上,最好使用 R 和 SQL

我可以为 dapper-dot-net 映射指定数据库列名称吗?

是否应该强制执行参照完整性?

如何在 MSSQL 2005 中创建递归查询?

触发器内的多个插入/更新语句?

SQL查询7天前的数据

如何决定使用什么 [Sqlite、Realm、CoreData、User-default、JSON 文件] 来存储 iOS 数据?

用于 Java 桌面应用程序的最佳数据库是什么

限制一个 sqlite 表的最大行数

没有自动增量的sqlalchemy主键

A QuerySet 按聚合字段值

从 CSV 文件填充 Android 数据库?

PostgreSQL 的示例数据库

获取 xp_cmdshell 的执行权限