Como puedo entender la documentación, las siguientes definiciones son equivalentes:
create table foo (
id serial primary key,
code integer,
label text,
constraint foo_uq unique (code, label));
create table foo (
id serial primary key,
code integer,
label text);
create unique index foo_idx on foo using btree (code, label);
Sin embargo, una nota en el manual de Postgres 9.4 dice:
La forma preferida de agregar una restricción única a una tabla es
ALTER TABLE ... ADD CONSTRAINT
. El uso de índices para imponer restricciones únicas podría considerarse un detalle de implementación al que no se debe acceder directamente.
(Editar: esta nota se eliminó del manual con Postgres 9.5).
¿Es solo una cuestión de buen estilo? ¿Cuáles son las consecuencias prácticas de elegir una de estas variantes (por ejemplo, en el rendimiento)?
sql
postgresql
unique
Adam Piotrowski
fuente
fuente
Respuestas:
Tenía algunas dudas sobre este tema básico pero importante, así que decidí aprender con el ejemplo.
Creemos la tabla maestra de prueba con dos columnas, con_id con restricción única e ind_id indexada por índice único.
En la descripción de la tabla (\ d en psql) puede distinguir la restricción única del índice único.
Unicidad
Verifiquemos la unicidad, por si acaso.
Funciona como se esperaba!
Llaves extranjeras
Ahora definiremos la tabla de detalles con dos claves foráneas que hacen referencia a nuestras dos columnas en master .
Bueno, no hay errores. Asegurémonos de que funcione.
Se puede hacer referencia a ambas columnas en claves foráneas.
Restricción usando índice
Puede agregar restricciones de tabla utilizando un índice único existente.
Ahora no hay diferencia entre la descripción de restricciones de columna.
Índices parciales
En la declaración de restricción de tabla no puede crear índices parciales. Viene directamente de la definición de
create table ...
. En la declaración de índice único, puede configurarWHERE clause
para crear un índice parcial. También puede crear un índice en la expresión (no solo en la columna) y definir algunos otros parámetros (clasificación, orden de clasificación, colocación de NULL).No puede agregar restricción de tabla utilizando índice parcial.
fuente
Una ventaja más de usar
UNIQUE INDEX
vs.UNIQUE CONSTRAINT
es que puedes fácilmenteDROP
/CREATE
un índiceCONCURRENTLY
, mientras que con una restricción no puedes.fuente
El texto completo
Entonces el rendimiento de la velocidad debería ser el mismo
fuente
Otra cosa que he encontrado es que puedes usar expresiones sql en índices únicos pero no en restricciones.
Entonces, esto no funciona:
pero siguiendo obras.
fuente
citext
extensión.Dado que varias personas han proporcionado ventajas de índices únicos sobre restricciones únicas, aquí hay un inconveniente: una restricción única puede diferirse (solo se verifica al final de la transacción), un índice único no puede serlo.
fuente
Leí esto en el documento:
Así que creo que es lo que ustedes llaman "unicidad parcial" al agregar una restricción.
Y, sobre cómo garantizar la singularidad:
Por lo tanto, debemos agregar una restricción, que crea un índice, para garantizar la unicidad.
¿Cómo veo este problema?
Una "restricción" tiene como objetivo asegurar de manera gramatical que esta columna sea única, establece una ley, una regla; mientras que "index" es semántico , acerca de "cómo implementar, cómo lograr la unicidad, qué significa unico cuando se trata de implementación". Entonces, la forma en que Postgresql lo implementa es muy lógica: primero, declara que una columna debe ser única, luego Postgresql agrega la implementación de agregar un índice único para usted .
fuente
where
cláusula, por lo que puede definir que los registros son IFF únicos que satisfacen algunos criterios. Esto simplemente deshabilita las restricciones para un conjunto indefinido de registros que son anteriores a la restricción que se está creando. Es completamente diferente, y este último es significativamente menos útil, aunque es conveniente para migraciones progresivas, supongo.Hay una diferencia en el bloqueo.
Agregar un índice no bloquea el acceso de lectura a la tabla.
Agregar una restricción pone un bloqueo de tabla (por lo que todas las selecciones están bloqueadas) ya que se agrega a través de ALTER TABLE .
fuente
Algo muy pequeño que se puede hacer solo con restricciones y no con índices es usar la
ON CONFLICT ON CONSTRAINT
cláusula ( ver también esta pregunta ).Esto no funciona:
Produce:
Convierta el índice en una restricción:
Y la
INSERT
declaración ahora funciona.fuente