【发布时间】:2014-11-08 18:53:36
【问题描述】:
我有简单的类别表。类别可以有父类别(par_cat 列),如果是主类别并且父类别相同,则不应有 2 个或多个具有相同名称或 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`);
问题是,即使我有唯一的键,它也不起作用。如果我尝试将par_cat 设置为null 且名称和url 相同的2 个类别插入数据库,那么这2 个类别可以毫无问题地插入数据库(它们不应该)。但是,如果我为其他类别选择 par_cat(例如 1 假设存在 id 1 的类别),则只会插入第一条记录(这是所需的行为)。
问题 - 如何处理这种情况?我读到:
一个 UNIQUE 索引创建一个约束,使得索引中的所有值 必须是不同的。如果您尝试添加一个带有 与现有行匹配的键值。此约束不适用 除 BDB 存储引擎外,为 NULL 值。对于其他发动机,一个 UNIQUE 索引允许包含多个 NULL 值的列 空值。如果为 UNIQUE 索引中的列指定前缀值, 列值在前缀中必须是唯一的。
但是,如果我在多个列上具有唯一性,我预计情况并非如此(只有 par_cat 可以为空,name 和 url 不能为空)。因为par_cat 引用了同一个表的id,但某些类别没有父类别,它应该允许null 值。
【问题讨论】:
-
This answer 可以解释您遇到的问题。建议您将 par_cat 更改为不为 null,为 root 设置一个 minimun id,例如 0。并从 1 自动增加类别 ID。
-
@JaugarChang 但是我也有
par_cat的外键约束,所以我不能使用值0因为没有 id 为 0 的记录 -
或者你可以添加一个 id 为 0 的根记录。但我认为没有必要使用外键。您最好在应用程序端而不是数据库端强制执行引用完整性。
标签: mysql sql database unique-constraint