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
regclassaide à 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 sontsmallintetsmallint[]respectivement. Convertir enintegerpour 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
C1etC2au moment de la création, vous devez utiliserc1etc2dans 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.