PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So finden Sie heraus, ob für bestimmte Spalten eine eindeutige Schlüsselbeschränkung vorhanden ist

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 sind smallint und smallint[] beziehungsweise. In integer 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 und C2 Zum Zeitpunkt der Erstellung müssen Sie c1 verwenden und c2 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:

->SQLfiddle

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.