多对多自引用表
Posted
技术标签:
【中文标题】多对多自引用表【英文标题】:Many-to-many self-referential table 【发布时间】:2010-11-11 02:40:38 【问题描述】:有没有好办法实现单表行间的多对多关系?
示例:存储单词同义词的表:
-- list of words
CREATE TABLE word (
id integer PRIMARY KEY,
word varchar(32) NOT NULL UNIQUE
);
INSERT INTO words (id, word) VALUES (1, 'revolve');
INSERT INTO words (id, word) VALUES (2, 'rotate');
-- M:M link between words
CREATE TABLE word_link (
word1 integer REFERENCES word(id) NOT NULL,
word2 integer REFERENCES word(id) NOT NULL,
PRIMARY KEY (word1, word2)
);
明显的解决方案导致可能不是 1NF 表,包含重复数据:
INSERT INTO word_link(word1, word2) VALUES (1, 2);
INSERT INTO word_link(word1, word2) VALUES (2, 1);
虽然可以通过添加 (word1
那么有没有更好的(希望是通用的)方法来实现这种 M:M 关系?
【问题讨论】:
【参考方案1】:在这种情况下,我会在 UPDATE 和 INSERT 上添加一个 CHECK CONSTRAINT 以强制 word1 始终小于 word2,反之亦然。
【讨论】:
【参考方案2】:我将创建一个如下视图:
select distinct
case when word1 < word2 then word1 else word2 end as word1,
case when word1 < word2 then word2 else word1 end as word2
from
word_link
这样,您始终拥有一个干净、没有重复且易于从中选择的列表。我发现这与建立多对多关系的方式一样干净。
【讨论】:
嗯...您的案例陈述对这两种情况都有相同的标准。我想你的意思是 word2 @Nathan:同样的条件,不同的结果。第一列总是使用较小的词,而第二列总是使用最大的。 问题不在于摆脱重复的 word_link(CHECK CONSTRAINT 可以完成所有工作),而是查询需要它们:“SELECT w.* FROM word w JOIN wold_link wl ON w .id=wl.word2 AND wl.word1=2" 不会返回 (1, 'revolve')。所以选择是在臃肿的查询“... ON (w.id=wl.word2 AND wl.word1=2) OR (w.id=wl.word1 AND wl.word1=1)”和具有一致性的臃肿表之间建立触发器以上是关于多对多自引用表的主要内容,如果未能解决你的问题,请参考以下文章