PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment créer une table Postgres avec une clé primaire combinée unique ?

Créer un index unique :

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

Ne peut pas être un UNIQUE ou PRIMARY KEY contrainte, car celles-ci ne fonctionnent qu'avec des colonnes, pas des expressions.

Vous pouvez ajouter un serial colonne pour servir de PK, mais avec seulement deux colonnes d'entiers, votre PK d'origine est également très efficace (voir les commentaires). Et cela rend les deux colonnes NOT NULL automatiquement. (Sinon, ajoutez NOT NULL contraintes.)

Vous pouvez également ajouter un CHECK contrainte pour exclure les joueurs jouant contre eux-mêmes :

CHECK (winner <> loser)

Astuce :Pour rechercher une paire d'ID (où vous ne savez pas qui a gagné), créez les mêmes expressions dans votre requête, et l'index sera utilisé :

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

Si vous traitez des paramètres inconnus et que vous ne savez pas à l'avance lequel est le plus élevé :

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

Le wrapper CTE est juste pour faciliter la saisie des paramètres une seule fois et n'est pas nécessaire dans certains contextes.