PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да разберете дали съществува ограничение за уникален ключ за дадени колони

Можете да направите заявка в системните каталози за уникални ограничения , по-специално pg_constraint и 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;
  • тип идентификатор на обект regclass помага за недвусмислено идентифициране на вашата таблица.

  • Информационната функция на системния каталог pg_get_constraintdef() ви дава добре форматирана информация, която не е строго необходима за вашата заявка.

  • Използване също на оператори за масив <@ и @> за да сте сигурни, че масивите съвпадат напълно. (Редът на колоните е неизвестен.) Системните колони са smallint и smallint[] съответно. Прехвърляне към цяло число за да работи с тези оператори.

  • Имената на колоните са чувствителни към главни и малки букви, когато ги търсите директно в системния каталог. Ако не сте поставили в двойни кавички C1 и C2 по време на създаване, трябва да използвате c1 и c2 в този контекст.

  • Може да има и ограничение за първичен ключ с няколко колони налагане на уникалност. За да покриете това в заявката, използвайте вместо това:

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

Надграждайки цигулката на @Roman, този също демонстрира случая pk:

->SQLfiddle

Уникален индекс

И двете от горните (уникални и pk ограничения) се изпълняват чрез уникален индекс. В допълнение може да има и уникални индекси правейки ефективно същото като официално декларираното уникално ограничение. За да хванете всички потърсете системния каталог pg_index вместо това по подобен начин:

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;

Специална трудност тук е вътрешният тип int2vector . Аз се справям с това, като прехвърлям текст и конвертирам в int[] .

Имайте предвид, че внедряването на каталожни таблици може да се промени в основните. Малко вероятно е тези заявки да се повредят, но е възможно.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rails 3.2 Postgres Save Error ActiveRecord::StatementInvalid:PG::Error:ERROR:Синтактична грешка близо до 'T' на позиция 5

  2. PGSQL не е зареден в PHP 5.3 Windows под IIS

  3. Postgres - Подаване на името на таблицата като параметър и съхраняване на резултата във файл

  4. Съпоставяне на сериен тип PostgreSQL с анотации за хибернация

  5. Разрешете вмъкване само от тригер