MySQL:标准化内容类型、类别和子类别

MySQL: Normalizing content types, categories, and subcategories

我有以下基本table结构

内容的类别应与其类型相匹配,这一点很重要。

同样,内容的子类别应与其类别相匹配。

我知道目前这是对不匹配数据的广泛开放。例如,内容记录可能具有其类型不允许的类别和其类别不允许的子类别。

我如何更改 table 结构以防止这种情况发生?还是我应该坚持使用应用程序逻辑?

请求架构

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`)
)

在MySQL中您只能添加基本约束。您无法添加条件约束(很想看到)。

或者,您可以在 INSERT/UPDATE 触发之前构建检查。并使用 SIGNAL 取消 INSERT/UPDATE(参见 https://dev.mysql.com/doc/refman/5.5/en/signal.html

TBH 我认为如果您有“第 3 方”系统 直接 与数据库对话,它可能会成为一个 true 问题。如果没有,您可以在您的应用程序中解决它。逻辑,并为第 3 方访问创建 API。

如果你真的想在 RDBMS 级别解决这个问题,你可以看看 PostgreSQL(通过 CHECK)。

注意:关于您的 table 类别,我会 考虑 添加一个 parent_id 并将其保留在一个 table 中(自我关系)。这将允许嵌套您的类别已通过第二级。

在类别 table 中,为 (id, content_type_id) 创建唯一索引。在子类别 table 中,在 (id, category_id).

上创建唯一索引

然后在内容 table 中,像这样创建 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 )

类别和子类别 table 中的 FK 保持不变。

由于子类别依赖于内容类型的类别,因此使 FK 引用反映相同的依赖链。现在,在内容 table 中输入 type_id 后,类别和子类别值必须属于正确的依赖链。

但是,如果您需要更改内容条目的类型,则必须先将 category_id 和 sub_category_id 更改为 NULL,修改 type_id,然后插入正确的值进入 category_id 和 sub_category_id。为可靠的数据完整性付出的代价很小。