sql >> Database >  >> RDS >> PostgreSQL

Hoe te achterhalen of er een unieke sleutelbeperking bestaat voor bepaalde kolommen

U kunt de systeemcatalogi opvragen voor unieke beperkingen , in het bijzonder pg_constraint en 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;
  • Het type objectidentificatie regclass helpt om uw tafel ondubbelzinnig te identificeren.

  • De informatiefunctie van de systeemcatalogus pg_get_constraintdef() krijgt u mooi opgemaakte informatie, die niet strikt noodzakelijk is voor uw verzoek.

  • Ook met behulp van array-operators <@ en @> om ervoor te zorgen dat de arrays volledig overeenkomen. (De volgorde van de kolommen is onbekend.) De systeemkolommen zijn smallint en smallint[] respectievelijk. Casten naar integer om het met die operators te laten werken.

  • Kolomnamen zijn hoofdlettergevoelig wanneer u ze rechtstreeks in de systeemcatalogus opzoekt. Als je C1 niet dubbel hebt gequote en C2 bij het maken moet je c1 . gebruiken en c2 in deze context.

  • Er kan ook een primaire sleutelbeperking met meerdere kolommen zijn uniciteit afdwingen. Gebruik in plaats daarvan om dat in de query te behandelen:

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

Voortbouwend op de viool van @Roman, demonstreert deze ook de pk-zaak:

->SQLfiddle

Unieke index

Beide bovenstaande (unieke en pk-beperkingen) worden geïmplementeerd door middel van een unieke index. Daarnaast kunnen er ook unieke indices . zijn doet in feite hetzelfde als formeel verklaarde unieke beperking. Om allemaal te vangen doorzoek de systeemcatalogus pg_index in plaats daarvan, op een vergelijkbare manier:

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;

Speciale moeilijkheid hier is het interne type int2vector . Ik behandel het door tekst te casten en te converteren naar int[] .

Houd er rekening mee dat de implementatie van catalogustabellen kan veranderen in de belangrijkste. Het is onwaarschijnlijk dat deze zoekopdrachten kapot gaan, maar het is mogelijk.



  1. Meerdere maximale waarden in een query

  2. Tel en groepeer niet-lege waarden in MySQL

  3. SQL Server 2016:Verbeteringen voor beschikbaarheidsgroepen

  4. Excel ODBC Data Connection Query-tijd nodig om elke query te vernieuwen