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

Agregar restricción para hacer que la columna sea única por grupo de filas

Me gusta /a> , status realmente debería ser boolean . Más barato, más limpio.

De cualquier manera, puede imponer su regla con un índice único parcial :

Para permitir cero o una fila con status = 'Active' en toda la tabla :

CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';

Para permitir cero o una fila con status = 'Active' por userid , crea userid la columna indexada:

CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';

Tenga en cuenta que userid IS NULL no desencadenaría infracciones únicas, porque dos valores NULL nunca se consideran iguales. userid debe ser establecer NOT NULL en este caso.

¿Por qué indexar y no restringir?

Abordar su pregunta en el comentario :Este es un índice, no un CONSTRAINT .

El índice para el primer caso es pequeño , con una o ninguna fila.
El índice para el segundo caso contiene una fila por userid existente , pero es la forma más barata y rápida , además de ser limpio y seguro. Necesitaría un índice para verificar otras filas en cualquier caso para hacer esto rápido.

No puede tener un CHECK verificación de restricciones en otras filas, al menos no de una manera limpia y confiable. Hay formas que ciertamente no recomendaría para este caso:

Si usa un UNIQUE restricción en (userid, status) (¡que también se implementa con un índice único en segundo plano!), no puede hacerlo parcial y todos las combinaciones se imponen para ser únicas. podrías Todavía use esto si trabaja con status IS NULL para todos los casos excepto el 'Active' caso. Pero eso en realidad impondría un índice mucho más grande que incluiría a todos filas.