Restricción de columna única personalizada, solo aplicada si una columna tiene un valor específico


19

¿Es posible tener una restricción de columna única personalizada de la siguiente manera? Supongamos que tengo dos cols subsety typeambas cadenas (aunque los tipos de datos probablemente no importen).

Si typees "verdadero", entonces quiero que la combinación de typey subsetsea ​​única. De lo contrario, no hay restricción. Estoy usando PostgreSQL 8.4 en Debian.


Respuestas:


31

En otras palabras, quieres subsetser único si type = 'true'.
Un índice único parcial hará eso:

CREATE UNIQUE INDEX tbl_some_name_idx ON tbl (subset) WHERE type = 'true';

De esta manera, incluso puede hacer combinaciones con NULLvalores únicos, que de otra manera no es posible, como se detalla en esta respuesta relacionada:
restricción única de múltiples columnas PostgreSQL y valores NULL


Gracias Erwin No vi esta opción cuando miré la documentación. Un enlace más directo es postgresql.org/docs/current/interactive/indexes-partial.html . Ver Ejemplo 11-3.
Faheem Mitha

@FaheemMitha: vinculé un nivel más alto, ya que necesitas combinar un índice parcial con un índice único .
Erwin Brandstetter

1
@Erwin Esa página (sobre índices parciales), tiene un ejemplo con índice único parcial.
ypercubeᵀᴹ

@ypercube: Ah, cierto. Ese es el mejor enlace. Cambié mi respuesta para señalar ese último capítulo.
Erwin Brandstetter

6

Esto es complementario a la respuesta anterior de Erwin, pero PostgreSQL admite varios tipos de índices. Estos no son generalmente mutuamente excluyentes. Puedes pensar en esto como:

  • Método de índice (btree, GiST, GIN, etc.). Elija uno, si es necesario (btree es el predeterminado)
  • Parcial o completo. Si es parcial, use una cláusula where
  • Directo o funcional. Puede indexar la salida de funciones.
  • Único o no único

Todos estos se pueden combinar de varias maneras. Todo lo que está haciendo aquí es usar las características únicas y parciales, de modo que le brinde índices únicos parciales (que son extremadamente útiles a medida que los descubre).

Pero suponga que desea tener un índice que no distinga entre mayúsculas y minúsculas en el campo del subconjunto donde el tipo es verdadero. Luego agregaría una definición funcional:

CREATE INDEX my_index_name_idx_u ON tbl (lower(subset)) WHERE type;

Tenga en cuenta que esto crea un índice único en la salida de la función lower () llamada en el atributo del subconjunto donde type es verdadero.


Entonces, el índice en la respuesta de Erwin es directo, mientras que el de su ejemplo en funcional, ¿correcto?
Faheem Mitha

@FaheemMitha: Correcto.
Erwin Brandstetter
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.