Puede consultar los catálogos del sistema
para restricciones únicas , en particular pg_constraint
y pg_attribute
:
SELECT c.conname, pg_get_constraintdef(c.oid)
FROM pg_constraint c
JOIN (
SELECT array_agg(attnum::int) AS attkey
FROM pg_attribute
WHERE attrelid = 'tb'::regclass -- table name optionally schema-qualified
AND attname = ANY('{c1,c2}')
) a ON c.conkey::int[] <@ a.attkey AND c.conkey::int[] @> a.attkey
WHERE c.contype = 'u'
AND c.conrelid = 'tb'::regclass;
-
El tipo de identificador de objeto
regclass
ayuda a identificar sin ambigüedades su tabla. -
La función de información del catálogo del sistema
pg_get_constraintdef()
obtiene información con un buen formato, que no es estrictamente necesaria para su solicitud. -
También usando operadores de matriz
<@
y@>
para asegurarse de que las matrices coincidan completamente. (Se desconoce el orden de las columnas). Las columnas del sistema sonsmallint
ysmallint[]
respectivamente. Convertir ainteger
para que funcione con esos operadores. -
Los nombres de las columnas distinguen entre mayúsculas y minúsculas cuando se buscan directamente en el catálogo del sistema. Si no entrecomillas dobles
C1
yC2
en el momento de la creación, debe usarc1
yc2
en este contexto. -
También podría haber una restricción de clave principal de varias columnas imponer la unicidad. Para cubrir eso en la consulta, use en su lugar:
WHERE c.contype IN ('u', 'p')
Basado en el violín de @Roman, este también demuestra el caso pk:
Índice único
Ambos de los anteriores (restricciones únicas y de pk) se implementan mediante un índice único. Además también puede haber índices únicos haciendo efectivamente lo mismo que la restricción única declarada formalmente. Para atraparlos a todos consultar el catálogo del sistema pg_index
en cambio, de manera similar:
SELECT c.relname AS idx_name
FROM (
SELECT indexrelid, string_to_array(indkey::text, ' ')::int[] AS indkey
FROM pg_index
WHERE indrelid = 'tb'::regclass
AND indisunique -- contains "indisprimary"
) i
JOIN (
SELECT array_agg(attnum::int) AS attkey
FROM pg_attribute
WHERE attrelid = 'tb'::regclass
AND attname = ANY('{c1,c2}')
) a ON i.indkey <@ a.attkey AND i.indkey @> a.attkey
JOIN pg_class c ON c.oid = i.indexrelid;
La dificultad especial aquí es el tipo interno int2vector
. Lo trato enviando texto y convirtiéndolo a int[]
.
Tenga en cuenta que la implementación de las tablas de catálogo puede cambiar entre las principales. Es poco probable que estas consultas se rompan, pero es posible.