概述:我试图表示数据库中几种类型的实体,它们具有许多共同的基本字段,然后每个实体都具有一些其他字段,这些字段不与其他类型的实体共享。工作流通常会涉及将实体一起列出,因此我决定要有一个带有其公共字段的表,然后每个实体都将具有自己的表及其附加字段。
要实现:所有实体都拥有一个共同的领域“
tatus”;但是,某些实体将仅支持所有可能状态的子集。我还希望每种类型的实体都强制使用其状态子集。最后,我还将希望在将实体一起列出时将其包括在内,因此将其从一组通用字段中排除似乎是不正确的,因为这将需要特定类型表的并集,并且在其中缺少``实现接口’‘。
SQL意味着包含该字段将是约定俗成的。
我为什么在这里:以下是可以使用的解决方案,但是如果有更好或更通用的方法来解决问题,我很感兴趣。特别是,这种解决方案需要我做出多余的unique
约束,而多余的状态字段却让人感到不舒服。
create schema test;
create table test.statuses(
id integer primary key
);
create table test.entities(
id integer primary key,
status integer,
unique(id, status),
foreign key (status) references test.statuses(id)
);
create table test.statuses_subset1(
id integer primary key,
foreign key (id) references test.statuses(id)
);
create table test.entites_subtype(
id integer primary key,
status integer,
foreign key (id) references test.entities(id),
foreign key (status) references test.statuses_subset1(id),
foreign key (id, status) references test.entities(id, status) initially deferred
);
一些数据:
insert into test.statuses(id) values
(1),
(2),
(3);
insert into test.entities(id, status) values
(11, 1),
(13, 3);
insert into test.statuses_subset1(id) values
(1), (2);
insert into test.entites_subtype(id, status) values
(11, 1);
-- Test updating subtype first
update test.entites_subtype
set status = 2
where id = 11;
update test.entities
set status = 2
where id = 11;
-- Test updating base type first
update test.entities
set status = 1
where id = 11;
update test.entites_subtype
set status = 1
where id = 11;
/* -- This will fail
insert into test.entites_subtype(id, status) values
(12, 3);
*/
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列(主要实体):
顺便说一句,根据文档:
如果
refcolumn
省略列表,reftable
则使用的主键。
演示数据:
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 (包括您的测试)。
另一个选择是将的所有组合输入(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
等等。
相关答案:
如果出于某种原因不需要所有四个表,请考虑对dba.SE上一个非常类似的问题进行详细的解决:
…可能是您描述的另一种选择。如果您可以忍受一些主要限制。相关答案:
问题内容: 我有一种类似于以下的双向外交关系 我如何将Parent.favoritechild的选择限制为仅其父母为自己的孩子?我试过了 但这会导致管理界面未列出任何子项。 问题答案: 我刚刚在Django文档中碰到。尚不确定这是如何工作的,但在这里可能是正确的事情。 允许指定常量,可调用对象或Q对象以限制键的允许选择。常量在这里显然没有用,因为它对所涉及的对象一无所知。 使用可调用(函数或类方法
问题内容: 我如何在MySQL中应用distinct关键字,以便仅检查一个列字段是否唯一,同时仍从表中返回其他列? 问题答案: 为了能够做到这一点,mysql必须知道如何处理其他列。您GROUP BY列应该是唯一的,并使用一个函数来告诉它如何处理其他列(所谓的 汇总函数 )。和是常见的例子:
本文向大家介绍关系类型,包括了关系类型的使用技巧和注意事项,需要的朋友参考一下 X和Y或E上的集合之间的空关系是空集合∅ 集合X和Y之间的完全关系为集合X×Y 集合X上的身份关系是集合{(x,x)| x∈X} 关系R的逆关系R'定义为-R'= {(b,a)| (a,b)∈R} 示例-如果R = {(1,2),(2,3)},则R'将是{(2,1),(3,2)} 如果∀a∈A与a相关(aRa成立),则
问题内容: 我有一个用户表和一个朋友表。朋友表拥有两个外键,分别指向我的用户表和状态字段。我试图能够从Friend对象上的User表中调用属性。例如,我希望能够执行诸如friend.name或friend.email之类的操作。 当我得到对象时,我所拥有的只是2,并且我想显示每个用户的所有属性,以便可以在表单等中使用该信息。我对sqlalchemy还是陌生的- 仍在尝试学习更高级的功能。这只是一个
我有一个奇怪的问题。 我有一个用户表和一个公司表。一个用户属于一家公司,而一家公司有许多用户。 表的两个主键都是id。 在laravel文档中,我阅读了以下内容: 此外,Eloquent假设外键的值应该与父项的id列匹配。 我在我的
null null 表名: ISBN->外键 authorid->外键 既然Linq-to-SQL会根据外键关系自动创建属性,为什么下面的代码块不会触发智能感知呢?对我来说不是... 它不允许我添加照片,但“author”与AuthorISBN有“一对多”关系,“titles”也与AuthorISBN有“一对多”关系 代码: