sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur man tar reda på om det finns en unik nyckelbegränsning för givna kolumner

Du kan fråga systemkatalogerna för unika begränsningar , särskilt pg_constraint och 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;
  • objektidentifieringstypen regclass hjälper till att entydigt identifiera din tabell.

  • Systemkataloginformationsfunktionen pg_get_constraintdef() ger dig snyggt formaterad information, vilket inte är absolut nödvändigt för din begäran.

  • Använder även arrayoperatorer <@ och @> för att se till att arrayerna matchar helt. (Kolumnernas ordning är okänd.) Systemkolumnerna är smallint och smallint[] respektive. Casta till integer för att få det att fungera med dessa operatörer.

  • Kolumnnamn är skiftlägeskänsliga när du letar upp dem direkt i systemkatalogen. Om du inte dubbelciterade C1 och C2 vid skapandet måste du använda c1 och c2 i detta sammanhang.

  • Det kan också finnas en primär nyckelbegränsning med flera kolumner upprätthålla unikhet. För att täcka det i frågan använd istället:

    WHERE  c.contype IN ('u', 'p')
    

Med utgångspunkt i @Romans fiol, visar den här också pk-fallet:

->SQLfiddle

Unikt index

Båda ovanstående (unika &pk-begränsningar) implementeras med hjälp av ett unikt index. Dessutom kan det också finnas unika index gör i praktiken samma sak som formellt deklarerade unika begränsningar. För att fånga alla fråga systemkatalogen pg_index istället på ett liknande sätt:

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;

Speciell svårighet här är den interna typen int2vector . Jag hanterar det genom att casta text och konvertera till int[] .

Var medveten om att implementeringen av katalogtabeller kan ändras över huvud. Osannolikt att dessa frågor går sönder, men möjligt.



  1. Postgresql generera_serie av månader

  2. Finns det något sätt att köra store_result och get_result tillsammans

  3. Min TO_DATE verkar inte fungera korrekt

  4. MySQL skiftlägeskänslig fråga