sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo crear una tabla de Postgres con una clave principal combinada única?

Cree un índice único:

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

No puede ser un UNIQUE o PRIMARY KEY restricción, ya que solo funcionan con columnas, no con expresiones.

Puede agregar un serial columna para servir como PK, pero con solo dos columnas de enteros, su PK original también es muy eficiente (ver comentarios). Y hace que ambas columnas NOT NULL automáticamente. (De lo contrario, agregue NOT NULL restricciones.)

También puede agregar un CHECK restricción para descartar jugadores jugando contra ellos mismos:

CHECK (winner <> loser)

Sugerencia:para buscar un par de ID (donde no sabe quién ganó), cree las mismas expresiones en su consulta y se usará el índice:

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

Si maneja parámetros desconocidos y no sabe cuál es mayor antes de tiempo:

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

El contenedor CTE es solo por conveniencia para ingresar parámetros una sola vez y no es necesario en algunos contextos.