【问题标题】: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 关系?

【问题讨论】:

    标签: database-design normalization


    【解决方案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)”和具有一致性的臃肿表之间建立触发器
      猜你喜欢
      • 2015-04-06
      • 2017-02-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-10
      • 1970-01-01
      • 2018-08-19
      • 2017-02-05
      相关资源
      最近更新 更多