Postgres: riferimento unico da A a B
-
18-09-2019 - |
Domanda
Voglio una corrispondenza biunivoca tra la coppia (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?
);
Non voglio di riferimento come ad esempio:
(PHP, Perl) points to 1 and 2,
3 points to (C#, null) and (Python, Elinks)
In altre parole, voglio che il riferimento da unici da (tag1, tag2) per tag (tag_id), non UNIQUE (tag1, tag2).
Soluzione
Questo potrebbe essere più simile a quello che stai cercando:
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)
);
Making 'tag_id' la chiave primaria significa che si può avere una sola voce con un dato 'tag_id', e che le ricerche basate su 'tag_id' sarà veloce.
L'indice sulla 'question_id' migliorerà la velocità di ricerca sulla base di 'question_id', che è quello che penso che stavi cercando di fare con la tua definizione PRIMARY KEY originale. Se si vuole veramente la (tag_id, question_id) coppia per essere unico, come si doveva, quindi aggiungere un UNICO (tag_id, question_id) in là, ma direi che si dovrebbe lasciare tag_id come chiave primaria.
Il vincolo unicità on (tag1, tag2) impedisce la mappatura inversa di avere duplicati.
Ecco alcuni esempi di ciò che può funzionare:
Opere:
1 -> (x, y)
2 -> (x, z)
fallisce (tag_id è una chiave primaria, e quindi è unica):
1 -> (x, y)
1 -> (y, x)
fallisce (la coppia (tag1, tag2) non riservate):
1 -> (x, y)
2 -> (x, y)
Tuttavia, la coppia (x, y) non è uguale alla coppia (y, x). Non sono sicuro di come catturare quel vincolo di unicità.