sql >> Database teknologi >  >> RDS >> PostgreSQL

Sådan finder du ud af, om der findes en unik nøglebegrænsning for givne kolonner

Du kan forespørge i systemkatalogerne for unikke begrænsninger , især pg_constraint og 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;
  • objektidentifikationstypen regclass hjælper med entydigt at identificere dit bord.

  • Systemkataloginformationsfunktionen pg_get_constraintdef() får dig pænt formateret information, hvilket ikke er strengt nødvendigt for din anmodning.

  • Bruger også array-operatorer <@ og @> for at sikre, at arrays matcher fuldstændigt. (Rækkefølgen af ​​kolonner er ukendt.) Systemkolonnerne er smallint og smallint[] henholdsvis. Cast til integer for at få det til at fungere med disse operatører.

  • Kolonnenavne skelner mellem store og små bogstaver, når de slås direkte op i systemkataloget. Hvis du ikke har citeret C1 dobbelt og C2 på oprettelsestidspunktet skal du bruge c1 og c2 i denne sammenhæng.

  • Der kan også være en primær nøglebegrænsning med flere kolonner håndhævelse af unikhed. For at dække det i forespørgslen, brug i stedet:

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

Med udgangspunkt i @Romans violin, demonstrerer denne også pk-sagen:

->SQLfiddle

Unikt indeks

Begge ovenstående (unikke &pk-begrænsninger) er implementeret ved hjælp af et unikt indeks. Derudover kan der også være unikke indekser gør effektivt det samme som formelt erklæret unik begrænsning. For at fange dem alle forespørg på systemkataloget pg_index i stedet på lignende måde:

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;

Særlig vanskelighed her er den interne type int2vector . Jeg håndterer det ved at caste tekst og konvertere til int[] .

Vær opmærksom på, at implementering af katalogtabeller kan ændre sig på tværs af store. Usandsynligt, at disse forespørgsler går i stykker, men muligt.



  1. Forståelse af MySQL key_len i Explain Statement

  2. MySql workbench-forespørgselshistorik (sidst udførte forespørgsel/forespørgsler) dvs. oprette/ændre tabel, vælge, indsætte opdateringsforespørgsler

  3. Hvorfor Datediff mellem GETDATE() og SYSDATETIME() i millisekunder er altid anderledes?

  4. Pandaer skriver dataramme til andre postgresql-skemaer