我有以下基本表格结构
内容
ContentType
分类
子类别
内容的类别应与其类型匹配非常重要。
同样,内容的子类别应与其类别相匹配。
我知道目前这对数据不匹配是敞开的。例如,内容记录可能具有其类型不允许的类别以及其类别不允许的子类别。
如何更改表格结构以防止此问题?或者我应该坚持使用应用程序逻辑?
按订单要求
CREATE TABLE `content_type` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
CREATE TABLE `category` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`content_type_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_category_content_type` FOREIGN KEY (`content_type_id`) REFERENCES `content_type` (`id`),
)
CREATE TABLE `sub_category` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`category_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_sub_category_category` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`),
)
CREATE TABLE `content` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`type_id` int(10) unsigned NOT NULL,
`category_id` int(10) unsigned DEFAULT NULL,
`sub_category_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_content_type` FOREIGN KEY (`type_id`) REFERENCES `content_type` (`id`),
CONSTRAINT `fk_content_category` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`)
CONSTRAINT `fk_content_sub_category` FOREIGN KEY (`sub_category_id`) REFERENCES `sub_category` (`id`)
)
答案 0 :(得分:1)
在MySQL中,您只能添加基本约束。你无法添加条件约束(很想看到它)。
或者,您可以在BEFORE INSERT / UPDATE TRIGGER中构建检查。并使用SIGNAL取消INSERT / UPDATE(请参阅https://dev.mysql.com/doc/refman/5.5/en/signal.html)
TBH我认为如果你有第三方'它可能会成为真正的问题。系统直接向数据库说话。如果没有,您可以在您的应用程序中解决它。逻辑,并为第三方访问创建API。
如果你真的想在RDBMS级别解决这个问题,你可以看看PostgreSQL(通过CHECK)。
注意:关于您的类别表,我会考虑添加parent_id并将其保存在一个表中(自我关系)。这样就可以让你的类别通过第二级了。
答案 1 :(得分:1)
在Category表中,在(id,content_type_id)上创建唯一索引。在SubCategory表中,在(id,category_id)上创建唯一索引。
然后在Content表中,创建如下的FK:
constraint FK_ContentCategory foreign key( category_id, type_id )
references Category( id, content_type_id )
constraint FK_ContentSubCategory foreign key( sub_category_id, category_id )
references SubCategory( id, category_id )
Category和SubCategory表中的FK保持不变。
由于子类别取决于依赖于内容类型的类别,因此使FK引用反映相同的依赖链。现在,一旦在Content表中输入type_id,类别和子类别值必须属于正确的依赖链。
但是,如果您需要更改Content条目的类型,则必须先将category_id和sub_category_id更改为NULL,修改type_id,然后将正确的值插入category_id和sub_category_id。为稳固的数据完整性付出的代价很小。