【问题标题】:Create two foreign key references to same table with unique composite index to one of them创建对同一个表的两个外键引用,其中一个具有唯一复合索引
【发布时间】:2015-02-24 22:05:01
【问题描述】:

items 表中的所有项目都有一个可以从item_category 表派生的类别。

+---------------------------------------------+
| items                                       |
+---------------------------------------------+
| id                 | PK                     |
+--------------------+------------------------+
| item_category_id   | FK(item_categories.id) |
+--------------------+------------------------+

item_category 表引用自身。我想创建一个类别->子类别->子子类别等系统。我不知道会有多少嵌套的子类别,所以我认为我最好的选择是将这个结构包含在一个表中。如果item_category_idNOT NULL,那么它有一个父类,否则它是一个超类并且没有父类。

+-------------------------------------------+
| item_categories                           |
+-------------------------------------------+
| id               | PK                     |
+------------------+------------------------+
| item_category_id | FK(item_categories.id) |
+------------------+------------------------+

这就是我的问题所在。 doll_item 表是一个数据透视表。基本上,doll 可以有很多物品,item 可以属于很多娃娃。但不仅如此。我想确保对于doll_item 表中的每个doll,其对应的item 都来自一个独特的类别。

我试图在每一行中为item 拉入item_category_id;但是,我担心这种关系不会强制items 表中的item_iditem_category_id 必须来自同一行。如果没有这个要求,在doll_item 表中添加后两行是没有意义的。

是否可以使用 MySQL 强制执行此操作?

+-------------------------------------------------------+
| doll_item                                             |
+-------------------------------------------------------+
| doll_id              | FK(dolls.id)                   |
+----------------------+--------------------------------+
| item_id              | FK(items.id)                   |
+----------------------+--------------------------------+
| item_category_id     | FK(items.item_category_id)     |
+----------------------+--------------------------------+
| unique(doll_item.doll_id, doll_item.item_category_id) |
+-------------------------------------------------------+

谢谢

【问题讨论】:

  • 澄清:您也有一个dolls 表,对吧?问题:当您说“数据透视”表时,您的意思是“多对多联接”表吗?问题:许多这样的连接表在两个id 列上都有一个复合(唯一)主键,在您的情况下为(doll_id, item_id)。是否有某些原因您不能这样做,因此从items 表中收集您唯一的item_category_id
  • 澄清:是的,有一个dolls 表。回答:是的,我所说的“数据透视”表是指有一个多对多连接表;这是doll_item 表。答:我需要一个比这更具体的约束。对于每个doll,我需要每个item_category 都有一个唯一的item。为了说明这一点,假设我有一个“裤子”项目。我不想让一个娃娃身上有两种不同类型的裤子。这是一个换装游戏,所以如果一个娃娃穿着两条裤子,它会显得很奇怪。你是什​​么意思“因此从items 表中收集你唯一的item_category_id?”
  • 离题但我忍不住:如果您打算允许任意深度的子类别,请考虑阅读this excellent thread
  • 谢谢!据我了解真的很有趣。尽管似乎具有邻接关系的节点可以有多个直接父节点,这对我的架构来说是个问题。还是我误解了,因为我看到面包屑的实现实际上类似于我的问题。

标签: mysql unique-constraint referential-integrity


【解决方案1】:

我想确保对于doll_item 表中的每个娃娃,[每个] 对应的item 都来自一个[不同的] 类别

使用复合UNIQUE KEY

我担心这种关系不会强制 items 表中的 item_iditem_category_id 必须来自同一行

使用复合FOREIGN KEY.:

CREATE TABLE item (
  id INT NOT NULL,
  item_category_id INT NOT NULL,
  PRIMARY KEY (id),
  INDEX (id, item_category_id) -- see note below
);

CREATE TABLE doll_item (
  doll_id INT NOT NULL,
  item_id INT NOT NULL,
  item_category_id INT NOT NULL,
  PRIMARY KEY (doll_id, item_id),

  UNIQUE KEY (doll_id, item_category_id),

  FOREIGN KEY (item_id, item_category_id)
    REFERENCES item (id, item_category_id)

);

注意:in the referenced table, there must be an index where the referenced columns are listed as the first columns in the same order.

【讨论】:

  • 这看起来很完美!谢谢:) ...关于你的笔记,你的意思是我的item 表中需要一个unique composite key 吗?或者您的意思是id 必须是数据库架构中item_category_id 之前的第一个字段? @随机种子
  • 它只意味着两个引用的列必须被任何类型的索引覆盖(常规、唯一、主键、诸如此类)。关于它们的部分必须“列为第一列 [在索引定义中]”意味着item(id, item_category_id, another_column) 上的索引也可以完成这项工作。另请参阅此手册页以获取相关的discussion on multi-column indexes
  • 我明白了......非常感谢......你的回答非常有帮助 - 我非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-04
  • 1970-01-01
  • 2019-12-23
相关资源
最近更新 更多