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

Nilai NULL untuk kolom referential_constraints.unique_constraint_* dalam skema informasi

Pengaturan pengujian

Anda mengasumsikan nama kendala test_def_abc_id_fkey , nama default yang dihasilkan dari pengaturan Anda di Postgres 11 atau lebih lama. Perlu dicatat, bahwa nama default telah ditingkatkan untuk Postgres 12, di mana pengaturan yang sama menghasilkan test_def_abc_id_abc_id2_fkey . Catatan rilis untuk Postgres 12:

Lihat:

db<>fiddle di sini

Jadi mari kita gunakan nama eksplisit test_def_abc_fkey untuk batasan FK untuk menghindari kebingungan:

CREATE TABLE test_abc (
  pk  int PRIMARY KEY
, id  int NOT NULL
, id2 int NOT NULL
);

CREATE UNIQUE INDEX test_abc_ids ON test_abc(id,id2);

CREATE TABLE test_def (
  id      int PRIMARY KEY
, abc_id  int
, abc_id2 int
, CONSTRAINT test_def_abc_fkey  -- !
     FOREIGN KEY (abc_id,abc_id2) REFERENCES test_abc(id,id2)
);

Dan berfungsi di Postgres 9.5 - Postgres 12.
Bahkan di Postgres 9.3.
(Saya telah mendapat kesan yang salah tentang batasan yang sebenarnya akan diperlukan.)

Jawab

Pengamatan Anda dari menanyakan skema informasi berlaku:

SELECT *
FROM   information_schema.referential_constraints
WHERE  constraint_name = 'test_def_abc_fkey';  -- unequivocal name

Kami mendapatkan satu baris, tetapi tiga bidang unique_constraint_catalog , unique_constraint_schema dan unique_constraint_name adalah NULL .

Penjelasannya tampaknya sederhana. Kolom-kolom itu menjelaskan, seperti yang dikatakan manual:

Tetapi tidak ada UNIQUE batasan , hanya UNIQUE indeks . Sebuah UNIQUE kendala diimplementasikan menggunakan UNIQUE indeks di Postgres. Batasan didefinisikan oleh standar SQL, indeks adalah detail implementasi. Ada perbedaan seperti yang Anda temukan. Terkait:

Tes yang sama dengan UNIQUE yang sebenarnya batasan menampilkan data seperti yang diharapkan:

db<>fiddle di sini

Jadi ini sepertinya masuk akal. Terutama karena skema informasi juga didefinisikan oleh komite standar SQL dan indeks tidak standar, hanya kendala. (Tidak ada informasi indeks dalam tampilan skema informasi.)

Semua jelas? Tidak cukup.

Namun

Ada tampilan skema informasi lain key_column_usage . Kolom terakhirnya digambarkan sebagai:

Tebal penekanan milikku. Di sini, posisi ordinal kolom di indeks tetap terdaftar:

SELECT *
FROM   information_schema.key_column_usage
WHERE  constraint_name = 'test_def_abc_fkey';

Lihat:

db<>fiddle di sini

Tampaknya tidak konsisten.

Yang lebih parah, manual mengklaim bahwa PRIMARY KEY actual yang sebenarnya atau UNIQUE batasan akan diperlukan untuk pembuatan FOREIGN KEY kendala:

Tampaknya menjadi bug dokumentasi ? Jika tidak ada yang bisa menunjukkan kesalahan saya di sini, saya akan mengajukan laporan bug.

Terkait:

Solusi

Di Postgres, katalog sistem adalah sumber kebenaran yang sebenarnya. Lihat:

Jadi Anda bisa menggunakan sesuatu seperti ini (seperti yang saya juga tambahkan di biola atas):

SELECT c.conname
     , c.conrelid::regclass  AS fk_table, k1.fk_columns
     , c.confrelid::regclass AS ref_table, k2.ref_key_columns
FROM   pg_catalog.pg_constraint c
LEFT   JOIN LATERAL (
   SELECT ARRAY (
      SELECT a.attname
      FROM   pg_catalog.pg_attribute a
           , unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord)
      WHERE  a.attrelid = c.conrelid
      AND    a.attnum = k.attnum
      ORDER  BY k.ord
      ) AS fk_columns
   ) k1 ON true
LEFT   JOIN LATERAL (
   SELECT ARRAY (
      SELECT a.attname
      FROM   pg_catalog.pg_attribute a
           , unnest(c.confkey) WITH ORDINALITY AS k(attnum, ord)
      WHERE  a.attrelid = c.confrelid
      AND    a.attnum = k.attnum
      ORDER  BY k.ord
      ) AS ref_key_columns
   ) k2 ON true
WHERE  conname = 'test_def_abc_fkey';

Pengembalian:

conname           | fk_table | fk_columns       | ref_table | ref_key_columns
:---------------- | :------- | :--------------- | :-------- | :--------------
test_def_abc_fkey | test_def | {abc_id,abc_id2} | test_abc  | {id,id2}       

Terkait:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Penyediaan Sendiri Akun Pengguna di PostgreSQL melalui Akses Anonim Tanpa Hak

  2. Migrasikan data SPASIAL dari Oracle ke Postgresql

  3. Menggunakan Barman untuk Pemulihan Bencana PostgreSQL

  4. Bermigrasi secara bertahap dari SQL Server ke PostgreSQL

  5. Bagaimana cara saya menulis kueri Django yang melakukan matematika tanggal ketika dieksekusi sebagai PostGres SQL?