Você pode consultar os catálogos do sistema para restrições exclusivas , em particular
pg_constraint
e 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;
-
O tipo de identificador de objetoregclass
ajuda a identificar inequivocamente sua tabela.
-
A função de informações do catálogo do sistemapg_get_constraintdef()
fornece informações bem formatadas, o que não é estritamente necessário para sua solicitação.
-
Também usando operadores de matriz<@
e@>
para garantir que as matrizes correspondam completamente. (A ordem das colunas é desconhecida.) As colunas do sistema sãosmallint
esmallint[]
respectivamente. Transmitir parainteger
para fazê-lo funcionar com esses operadores.
-
Os nomes das colunas diferenciam maiúsculas de minúsculas ao pesquisá-los diretamente no catálogo do sistema. Se você não colocou aspas duplasC1
eC2
no momento da criação, você deve usarc1
ec2
nesse contexto.
-
Também pode haver uma restrição de chave primária de várias colunas reforçando a singularidade. Para cobrir isso na consulta, use:
WHERE c.contype IN ('u', 'p')
Com base no violino de @Roman, este também demonstra o caso pk:
->SQLfiddle
Índice exclusivo
Ambos os itens acima (restrições exclusivas e pk) são implementados por meio de um índice exclusivo. Além disso, também pode haver índices exclusivos fazendo efetivamente o mesmo que a restrição exclusiva formalmente declarada. Para pegar todos consulte o catálogo do sistema
pg_index
em vez disso, de forma semelhante: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;
A dificuldade especial aqui é o tipo interno
int2vector
. Eu lido com isso lançando texto e convertendo para int[]
. Esteja ciente de que a implementação de tabelas de catálogo pode mudar entre os principais. É improvável que essas consultas quebrem, mas é possível.