PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie erstelle ich eine Postgres-Tabelle mit eindeutigem kombiniertem Primärschlüssel?

Erstellen Sie einen eindeutigen Index:

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

Darf kein UNIQUE sein oder PRIMARY KEY Einschränkung, da diese nur mit Spalten arbeiten, nicht mit Ausdrücken.

Sie können eine serial hinzufügen Spalte als PK dienen, aber mit nur zwei Integer-Spalten ist Ihre ursprüngliche PK auch sehr effizient (siehe Kommentare). Und es macht beide Spalten zu NOT NULL automatisch. (Andernfalls fügen Sie NOT NULL hinzu Beschränkungen.)

Sie können auch ein CHECK hinzufügen Einschränkung, um Spieler auszuschließen, die gegen sich selbst spielen:

CHECK (winner <> loser)

Tipp:Um nach einem ID-Paar zu suchen (wobei Sie nicht wissen, wer gewonnen hat), bauen Sie dieselben Ausdrücke in Ihre Abfrage ein, und der Index wird verwendet:

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

Wenn Sie es mit unbekannten Parametern zu tun haben und im Voraus nicht wissen, welcher der größere ist:

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

Der CTE-Wrapper dient nur der Bequemlichkeit, um Parameter nur einmal einzugeben, und ist in manchen Zusammenhängen nicht erforderlich.