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

Batasi hubungan kunci asing ke baris subtipe terkait

Sederhanakan pembuatan di MATCH SIMPLE perilaku kendala fk

Jika setidaknya satu kolom batasan asing multikolom dengan MATCH SIMPLE default perilakunya adalah NULL , batasan tidak diterapkan. Anda dapat membangunnya untuk menyederhanakan desain Anda.

CREATE SCHEMA test;

CREATE TABLE test.status(
   status_id  integer PRIMARY KEY
  ,sub        bool NOT NULL DEFAULT FALSE  -- TRUE .. *can* be sub-status
  ,UNIQUE (sub, status_id)
);

CREATE TABLE test.entity(
   entity_id  integer PRIMARY KEY
  ,status_id  integer REFERENCES test.status  -- can reference all statuses
  ,sub        bool      -- see examples below
  ,additional_col1 text -- should be NULL for main entities
  ,additional_col2 text -- should be NULL for main entities
  ,FOREIGN KEY (sub, status_id) REFERENCES test.status(sub, status_id)
     MATCH SIMPLE ON UPDATE CASCADE  -- optionally enforce sub-status
);

Ini sangat murah untuk menyimpan beberapa kolom NULL tambahan (untuk entitas utama):

BTW, per dokumentasi:

Demo-data:

INSERT INTO test.status VALUES
  (1, TRUE)
, (2, TRUE)
, (3, FALSE);     -- not valid for sub-entities

INSERT INTO test.entity(entity_id, status_id, sub) VALUES
  (11, 1, TRUE)   -- sub-entity (can be main, UPDATES to status.sub cascaded)
, (13, 3, FALSE)  -- entity  (cannot be sub,  UPDATES to status.sub cascaded)
, (14, 2, NULL)   -- entity  (can    be sub,  UPDATES to status.sub NOT cascaded)
, (15, 3, NULL)   -- entity  (cannot be sub,  UPDATES to status.sub NOT cascaded)

SQL Fiddle (termasuk tes Anda).

Alternatif dengan FK tunggal

Pilihan lain adalah memasukkan semua kombinasi (status_id, sub) ke dalam status tabel (hanya boleh ada 2 per status_id ) dan hanya memiliki satu batasan fk:

CREATE TABLE test.status(
   status_id  integer
  ,sub        bool DEFAULT FALSE
  ,PRIMARY KEY (status_id, sub)
);

CREATE TABLE test.entity(
   entity_id  integer PRIMARY KEY
  ,status_id  integer NOT NULL  -- cannot be NULL in this case
  ,sub        bool NOT NULL     -- cannot be NULL in this case
  ,additional_col1 text
  ,additional_col2 text
  ,FOREIGN KEY (status_id, sub) REFERENCES test.status
     MATCH SIMPLE ON UPDATE CASCADE  -- optionally enforce sub-status
);

INSERT INTO test.status VALUES
  (1, TRUE)       -- can be sub ...
  (1, FALSE)      -- ... and main
, (2, TRUE)
, (2, FALSE)
, (3, FALSE);     -- only main

dll.

Jawaban terkait:

Simpan semua tabel

Jika Anda memerlukan keempat tabel untuk beberapa alasan yang tidak ada dalam pertanyaan, pertimbangkan solusi terperinci ini untuk pertanyaan yang sangat mirip di dba.SE:

Warisan

... mungkin pilihan lain untuk apa yang Anda gambarkan. Jika Anda dapat hidup dengan beberapa batasan utama . Jawaban 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. Konversi detik ke yyyy-mm-dd jj:mm:dd PostgreSQL

  2. Pencarian teks lengkap pada substring di PostgreSQL

  3. Fungsi refactor sehingga dapat digunakan dalam CTE

  4. Fungsi Jendela atau Ekspresi Tabel Umum:hitung baris sebelumnya dalam jangkauan

  5. Cara menyiapkan pernyataan dan mengikat parameter di Postgresql untuk C++