PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Bagaimana menemukan apakah ada batasan kunci unik untuk kolom yang diberikan

Anda dapat menanyakan katalog sistem untuk batasan unik , khususnya pg_constraint dan 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;
  • Jenis pengenal objek regclass membantu mengidentifikasi tabel Anda dengan jelas.

  • Fungsi informasi katalog sistem pg_get_constraintdef() memberi Anda informasi yang diformat dengan baik, yang tidak sepenuhnya diperlukan untuk permintaan Anda.

  • Juga menggunakan operator array <@ dan @> untuk memastikan array benar-benar cocok. (Urutan kolom tidak diketahui.) Kolom sistem smallint dan smallint[] masing-masing. Transmisikan ke integer untuk membuatnya bekerja dengan operator tersebut.

  • Nama kolom peka huruf besar/kecil saat mencarinya di katalog sistem secara langsung. Jika Anda tidak mengutip dua kali C1 dan C2 pada waktu pembuatan, Anda harus menggunakan c1 dan c2 dalam konteks ini.

  • Mungkin juga ada batasan kunci utama multikolom menegakkan keunikan. Untuk menutupinya dalam kueri gunakan sebagai gantinya:

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

Membangun biola @Roman, yang ini juga menunjukkan kasus pk:

->SQLfiddle

Indeks unik

Kedua hal di atas (kendala unik &pk) diimplementasikan melalui indeks unik. Selain itu bisa juga ada indeks unik melakukan secara efektif sama dengan batasan unik yang dinyatakan secara formal. Untuk menangkap semuanya kueri katalog sistem pg_index sebagai gantinya, dengan cara yang sama:

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;

Kesulitan khusus di sini adalah tipe internal int2vector . Saya mengatasinya dengan mentransmisikan teks dan mengonversi ke int[] .

Ketahuilah bahwa implementasi tabel katalog mungkin berubah di seluruh jurusan. Tidak mungkin kueri ini rusak, tetapi mungkin.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tetapkan id yang sama ke baris dengan kombinasi data yang sama

  2. Untuk mengabaikan hasil SEBELUM PEMICU PostgreSQL?

  3. Hilangkan duplikat kota dari database

  4. Format Bulan dalam Angka Romawi di PostgreSQL

  5. Baris tidak dihapus karena pemicu kaskade memperbarui baris ini