PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Hạn chế mối quan hệ khóa ngoài đối với các hàng kiểu con có liên quan

Đơn giản hóa việc xây dựng trên MATCH SIMPLE hành vi của các ràng buộc fk

Nếu ít nhất một cột của ràng buộc ngoại đa cột với MATCH SIMPLE mặc định hành vi là NULL , ràng buộc không được thực thi. Bạn có thể xây dựng dựa trên đó để đơn giản hóa phần lớn thiết kế của mình.

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
);

Nó là rất rẻ để lưu trữ một số cột NULL bổ sung (cho các thực thể chính):

BTW, theo tài liệu:

Dữ liệu demo:

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 (bao gồm các bài kiểm tra của bạn).

Thay thế với FK đơn

Một tùy chọn khác là nhập tất cả các tổ hợp (status_id, sub) vào trạng thái status bảng (chỉ có thể có 2 trên mỗi status_id ) và chỉ có một ràng buộc fk duy nhất:

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

Vv.

Các câu trả lời liên quan:

Giữ tất cả các bảng

Nếu bạn cần cả bốn bảng vì lý do nào đó không có trong câu hỏi, hãy xem xét giải pháp chi tiết này cho một câu hỏi rất giống trên dba.SE:

Kế thừa

... có thể là một lựa chọn khác cho những gì bạn mô tả. Nếu bạn có thể sống với một số hạn chế chính . Câu trả lời liên quan:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kết hợp bát quái với tìm kiếm được xếp hạng trong django 1.10

  2. Cách chuyển đổi dấu thời gian thành số nguyên (Unix epoch) trong Postgres

  3. Go sql - phạm vi câu lệnh được chuẩn bị sẵn

  4. Cách không tạo tiện ích mở rộng PostgreSQL 9.0 trên nền tảng RPM

  5. Không thể sử dụng người dùng postgres trong cơ sở dữ liệu mới cho rails 3 trên máy chủ ubuntu 10.04