Postgres: única referência de A para B
-
18-09-2019 - |
Pergunta
Eu quero uma bijeção entre o par (tag1, tag2) e tag_id.
CREATE TABLE tags (
question_id INTEGER NOT NULL,
tag_id SERIAL NOT NULL,
tag1 VARCHAR(20),
tag2 VARCHAR(20),
PRIMARY KEY(question_id, tag_id),
(tag1, tag2) UNIQUE references tags(tag_id) #How?
);
Eu quero nenhuma referência, tais como:
(PHP, Perl) points to 1 and 2,
3 points to (C#, null) and (Python, Elinks)
Em outras palavras, eu quero que a referência a ser único FROM (tag1, tag2) para tags (TAG_ID), não UNIQUE (tag1, tag2).
Solução
Isso pode ser mais parecido com o que você está procurando:
CREATE TABLE tags (
question_id INTEGER NOT NULL,
tag_id SERIAL NOT NULL,
tag1 VARCHAR(20),
tag2 VARCHAR(20),
PRIMARY KEY (tag_id),
INDEX (question_id),
UNIQUE (tag1, tag2)
);
Fazer 'tag_id' os meios de chave primária que você pode ter apenas uma entrada com um dado 'tag_id', e que pesquisas com base em 'tag_id' será rápido.
O índice em 'question_id' irá melhorar a velocidade de pesquisa com base em 'question_id', que é o que eu acho que você estava tentando fazer com sua definição de chave primária original. Se você realmente quer o par (tag_id, question_id) para ser único, como você tinha, em seguida, adicione um UNIQUE (tag_id, question_id) lá dentro, mas eu diria que você deve deixar tag_id como chave primária.
A restrição de exclusividade sobre (tag1, tag2) impede o mapeamento inverso de ter duplicados.
Aqui estão alguns exemplos do que pode funcionar:
Works:
1 -> (x, y)
2 -> (x, z)
Falha (tag_id é uma chave primária, e, portanto, é único):
1 -> (x, y)
1 -> (y, x)
falha (o par (tag1, tag2) não é exclusivo):
1 -> (x, y)
2 -> (x, y)
No entanto, o par (x, y) não é igual ao par (y, x). Eu não sei como pegar essa restrição de exclusividade.