PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come creare una tabella Postgres con una chiave primaria combinata univoca?

Crea un indice univoco:

CREATE UNIQUE INDEX matches_uni_idx ON matches
   (greatest(winner, loser), least(winner, loser));

Non può essere un UNIQUE o PRIMARY KEY vincolo, poiché funzionano solo con le colonne, non con le espressioni.

Potresti aggiungere un serial colonna per fungere da PK, ma con solo due colonne intere, anche la tua PK originale è molto efficiente (vedi commenti). E rende entrambe le colonne NOT NULL automaticamente. (Altrimenti, aggiungi NOT NULL vincoli.)

Potresti anche aggiungere un CHECK vincolo per escludere i giocatori che giocano contro se stessi:

CHECK (winner <> loser)

Suggerimento:per cercare una coppia di ID (di cui non sai chi ha vinto), inserisci le stesse espressioni nella tua query e verrà utilizzato l'indice:

SELECT * FROM matches
WHERE  greatest(winner, loser) = 3  -- the greater value, obviously
AND    least(winner, loser) = 1;

Se hai a che fare con parametri sconosciuti e non sai in anticipo quale sia il maggiore:

WITH input AS (SELECT $id1 AS _id1, $id2 AS _id2)  -- input once
SELECT * FROM matches, input
WHERE  greatest(winner, loser) = greatest(_id1, _id2)
AND    least(winner, loser) = least(_id1, _id2);

Il wrapper CTE serve solo per comodità per inserire i parametri una sola volta e non è necessario in alcuni contesti.