代码之家  ›  专栏  ›  技术社区  ›  ymv

多对多自引用表

  •  3
  • ymv  · 技术社区  · 15 年前

    在单个表中,行之间是否有实现多对多关系的好方法?

    示例:存储单词同义词的表:

    -- 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<word2)检查来处理重复,但它使选择更加复杂(与普通联接相比,联合)并且非常任意。这个特定的例子可以从辅助表中获益(例如“意义”,所以单词m:n与公共意义相链接,而不是相互关联,从而提供更清晰的模式),但我对一些通用的解决方案感兴趣。

    那么,有没有更好的(希望也是常见的)实现这种m:m关系的方法呢?

    2 回复  |  直到 15 年前
        1
  •  1
  •   Felipe Lima    15 年前

    在本例中,我将在update和insert上添加一个check约束,以强制word1始终小于word2,反之亦然。

        2
  •  0
  •   Eric    15 年前

    我将创建如下视图:

    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
    

    这样,你总是有一个干净的,没有重复的列表,很容易从中选择。我发现这是一个干净的方式,你可以做一个多对多的关系。