你可以缩小UNIQUE KEY
到只有item1_id
. 这意味着该表定义了一种1:1
关系,而不是一种关系1:n
。此外,您可以删除auto_increment
主键,这些“链接”表中不需要它:
CREATE TABLE IF NOT EXISTS links (
item1_id int(20) NOT NULL,
item2_id int(20) NOT NULL,
PRIMARY KEY (item1_id),
FOREIGN KEY (item1_id) --- I assume you have these 2
REFERENCES item (item_id), --- Foreign Keys, too
FOREIGN KEY (item2_id)
REFERENCES item (item_id)
) ENGINE=InnoDB;
这与@gbn 的答案之间的区别在于,这不允许 Null,并且不需要任何来存储未链接的项目。两种设计的工作方式几乎相同,只是在插入/删除/更新语句中稍作修改。
不过,在这两种设计中,我们都可以有关联的夫妻,例如: (1 -> 2)
, (2 -> 3)
, (3 -> 7)
. 如果这符合所需的规范,那么两种设计都可以。
但是,如果我们只希望项目只出现在一对链接的对中,那么在链接的任一侧,实现起来就更难了。
一种方法是确保links
表中的所有插入都是通过插入两者(1, 2)
并(2, 1)
配对或失败的过程完成的(对于必须处理 2 行的删除/更新语句也是如此)。
其他更复杂的方法涉及触发器(或奇异结构,如索引视图,在 MySQL 中不可用)。
如果您想要规范化设计,还有这种方法(复杂但没有触发器):
CREATE TABLE IF NOT EXISTS link_help (
item1_id int(20) NOT NULL,
item2_id int(20) NOT NULL,
PRIMARY KEY (item1_id),
FOREIGN KEY (item1_id)
REFERENCES item (item_id),
FOREIGN KEY (item2_id)
REFERENCES item (item_id),
UNIQUE KEY (item1_id, item2_id) --- this will be needed below
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS links (
item1_id int(20) NOT NULL,
item2_id int(20) NOT NULL,
PRIMARY KEY (item1_id),
FOREIGN KEY (item1_id, item2_id)
REFERENCES link_help (item1_id, item2_id),
FOREIGN KEY (item2_id, item1_id) --- notice the different
REFERENCES link_help (item1_id, item2_id) --- order here
) ENGINE=InnoDB;
现在,您不能 在表中添加(1 -> 2)
, (2 -> 3)
,(3 -> 7)
行。links