简化基于[`MATCH
SIMPLE`](http://www.postgresql.org/docs/current/interactive/sql-
createtable.html)fk约束的行为
如果至少一列具有默认
MATCH SIMPLE行为的多列外部约束为
NULL,则不强制执行约束。您可以在此基础上大大简化您的设计。
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);
这是 很便宜 存放一些额外的NULL列(主要实体):
- 使用postgresql DB需要多少磁盘空间来存储NULL值?
顺便说一句,根据文档:
如果
refcolumn省略列表,reftable则使用的主键。
演示数据:
INSERT INTO test.status VALUES (1, TRUE), (2, TRUE), (3, FALSE); -- not valid for sub-entitiesINSERT 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 (包括您的测试)。
单个FK的替代方案
另一个选择是将的所有组合输入
(status_id, sub)到
status表中(每个只能有2个
status_id),并且只有一个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
等等。
相关答案:
- 完全匹配与简单匹配
- 仅当第三列不是NULL时,两列外键约束
- 当验证在另一个表上有条件时,数据库中的唯一性验证
保留所有桌子
如果出于某种原因不需要所有四个表,请考虑对dba.SE上一个非常类似的问题进行详细的解决:
- 强制约束“远离桌子”。
遗产
…可能是您描述的另一种选择。如果您可以忍受一些主要限制。相关答案:
- 在PostgreSQL中创建两种类型的表



