Само-ссылочная таблица «многие ко многим» - PullRequest
3 голосов
/ 15 июля 2009

Есть ли хороший способ реализовать отношение «многие ко многим» между строками в одной таблице?

Пример: таблица для хранения синонимов слов:

-- 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)
);

Очевидное решение приводит, вероятно, к таблице not-1NF, содержащей повторяющиеся данные:

INSERT INTO word_link(word1, word2) VALUES (1, 2);
INSERT INTO word_link(word1, word2) VALUES (2, 1);

Хотя дублирование можно устранить путем добавления проверки (word1

Так есть ли лучший (и, надеюсь, распространенный) способ реализации такого отношения M: M?

Ответы [ 2 ]

1 голос
/ 15 июля 2009

В этом случае я бы добавил CHECK CONSTRAINT в UPDATE и INSERT, чтобы принудительно указывать, что word1 всегда меньше word2 и наоборот.

0 голосов
/ 15 июля 2009

Я бы создал следующее представление:

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

Таким образом, у вас всегда есть чистый, без дубликатов список, из которого легко выбрать. Я обнаружил, что это примерно так же просто, как и отношения многих ко многим.

...