Sie können die Systemkataloge
abfragen für eindeutige Einschränkungen , insbesondere pg_constraint
und 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;
-
Der Objektkennungstyp
regclass
hilft, Ihren Tisch eindeutig zu identifizieren. -
Die Systemkatalog-Informationsfunktion
pg_get_constraintdef()
erhalten Sie schön formatierte Informationen, die für Ihre Anfrage nicht unbedingt erforderlich sind. -
Verwenden Sie auch Array-Operatoren
<@
und@>
um sicherzustellen, dass die Arrays vollständig übereinstimmen. (Die Reihenfolge der Spalten ist unbekannt.) Die Systemspalten sindsmallint
undsmallint[]
beziehungsweise. Ininteger
umwandeln damit es mit diesen Operatoren funktioniert. -
Bei Spaltennamen muss die Groß-/Kleinschreibung beachtet werden, wenn sie direkt im Systemkatalog nachgeschlagen werden. Wenn Sie
C1
nicht in doppelte Anführungszeichen gesetzt haben undC2
Zum Zeitpunkt der Erstellung müssen Siec1
verwenden undc2
in diesem Zusammenhang. -
Es könnte auch eine mehrspaltige Primärschlüsseleinschränkung geben Einzigartigkeit erzwingen. Um dies in der Abfrage abzudecken, verwenden Sie stattdessen:
WHERE c.contype IN ('u', 'p')
Aufbauend auf der Geige von @Roman demonstriert diese hier auch den pk-Fall:
Eindeutiger Index
Beide oben genannten (Eindeutigkeits- und pk-Einschränkungen) werden über einen eindeutigen Index implementiert. Darüber hinaus kann es auch eindeutige Indizes geben tut effektiv dasselbe wie eine formell deklarierte eindeutige Einschränkung. Um alle zu fangen Fragen Sie den Systemkatalog pg_index
ab
stattdessen auf ähnliche Weise:
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;
Besondere Schwierigkeiten bereitet hier der interne Typ int2vector
. Ich gehe damit um, indem ich Text umwandle und in int[]
umwandle .
Beachten Sie, dass sich die Implementierung von Katalogtabellen je nach Major ändern kann. Es ist unwahrscheinlich, dass diese Abfragen abbrechen, aber möglich.