Vous pouvez interroger les catalogues système
pour les contraintes uniques , en particulier pg_constraint
et 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;
-
Le type d'identifiant d'objet
regclass
aide à identifier sans ambiguïté votre table. -
La fonction d'informations sur le catalogue système
pg_get_constraintdef()
vous obtient des informations bien formatées, qui ne sont pas strictement nécessaires pour votre demande. -
Utilise également les opérateurs de tableau
<@
et@>
pour vous assurer que les tableaux correspondent complètement. (L'ordre des colonnes est inconnu.) Les colonnes système sontsmallint
etsmallint[]
respectivement. Convertir eninteger
pour le faire fonctionner avec ces opérateurs. -
Les noms de colonne sont sensibles à la casse lorsque vous les recherchez directement dans le catalogue système. Si vous n'avez pas mis entre guillemets
C1
etC2
au moment de la création, vous devez utiliserc1
etc2
dans ce contexte. -
Il peut également y avoir une contrainte de clé primaire multicolonne imposer l'unicité. Pour couvrir cela dans la requête, utilisez à la place :
WHERE c.contype IN ('u', 'p')
S'appuyant sur le violon de @Roman, celui-ci illustre également le cas pk :
Indice unique
Les deux contraintes ci-dessus (contraintes uniques et pk) sont implémentées au moyen d'un index unique. De plus, il peut également y avoir des indices uniques faire effectivement la même chose que la contrainte unique formellement déclarée. Pour les attraper tous interroger le catalogue système pg_index
à la place, de la même manière :
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 difficulté particulière ici est le type interne int2vector
. Je m'en occupe en diffusant du texte et en le convertissant en int[]
.
Sachez que l'implémentation des tables de catalogue peut changer d'un domaine à l'autre. Il est peu probable que ces requêtes échouent, mais c'est possible.