Можете да направите заявка в системните каталози
за уникални ограничения , по-специално pg_constraint
и 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;
-
тип идентификатор на обект
regclass
помага за недвусмислено идентифициране на вашата таблица. -
Информационната функция на системния каталог
pg_get_constraintdef()
ви дава добре форматирана информация, която не е строго необходима за вашата заявка. -
Използване също на оператори за масив
<@
и@>код> за да сте сигурни, че масивите съвпадат напълно. (Редът на колоните е неизвестен.) Системните колони са
smallint
иsmallint[]
съответно. Прехвърляне къмцяло число
за да работи с тези оператори. -
Имената на колоните са чувствителни към главни и малки букви, когато ги търсите директно в системния каталог. Ако не сте поставили в двойни кавички
C1
иC2
по време на създаване, трябва да използватеc1
иc2
в този контекст. -
Може да има и ограничение за първичен ключ с няколко колони налагане на уникалност. За да покриете това в заявката, използвайте вместо това:
WHERE c.contype IN ('u', 'p')
Надграждайки цигулката на @Roman, този също демонстрира случая pk:
Уникален индекс
И двете от горните (уникални и pk ограничения) се изпълняват чрез уникален индекс. В допълнение може да има и уникални индекси правейки ефективно същото като официално декларираното уникално ограничение. За да хванете всички потърсете системния каталог pg_index
вместо това по подобен начин:
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;
Специална трудност тук е вътрешният тип int2vector
. Аз се справям с това, като прехвърлям текст и конвертирам в int[]
.
Имайте предвид, че внедряването на каталожни таблици може да се промени в основните. Малко вероятно е тези заявки да се повредят, но е възможно.