[英]Foreign key to table A or table B
考虑这样一种情况,我定义了一个对象、一组对象,然后是一个将它们链接在一起的表:
CREATE TABLE obj (
id INTEGER PRIMARY KEY,
name text
) ;
CREATE TABLE group (
id INTEGER PRIMARY KEY ;
grpname TEXT
) ;
CREATE TABLE relation (
objid INTEGER,
grpid INTEGER,
PRIMARY KEY (objid, grpid)
) ;
我正在寻找适用的级联删除,所以我添加了外键
ALTER TABLE relation
ADD FOREIGN KEY (objid)
REFERENCES obj(id)
ON DELETE CASCADE ;
ALTER TABLE relation
ADD FOREIGN KEY (grpid)
REFERENCES group(id)
ON DELETE CASCADE ;
到目前为止一切正常。 现在假设我想添加对组组的支持。 我正在考虑像这样更改关系表:
CREATE TABLE relation_ver1 (
parent INTEGER,
child INTEGER,
PRIMARY KEY (parent, child)
) ;
ALTER TABLE relation_ver1
ADD FOREIGN KEY (parent)
REFERENCES group(id)
ON DELETE CASCADE ;
在这里,我提出了一个问题:我也想对 child 应用级联删除,但我不知道 child 是指组还是对象。
我可以向表 obj 或 group 添加外键吗?
我发现的唯一解决方案是添加 child_obj 和 child_grp 字段,添加相关外键,然后在插入对象时使用“特殊”(空类型)组,并在插入子组时执行相反的操作。
考虑关系:
relation_ver1(parent, child_obj, child_group)
我声称这种关系有以下缺点:
幸运的是,有一种简单的方法可以解决这个问题。 由于数据中存在多值依赖关系,您可以将表分解为 2 个符合 4NF 的较小表。 例如:
relation_ver_obj(parent, child_obj)
和relation_ver_grp(parent, child_group)
。
我们拥有外键的主要原因不是为了能够执行级联删除等操作。 存在外键的主要原因是参照完整性。
这意味着grpid
被声明为REFERENCES group(id)
以确保grpid
永远不会被允许采用任何在 group(id) 中找不到的值。 所以,这是一个有效性问题。 级联DELETE
也归结为有效性:如果删除了一个键,那么任何和所有引用该键的外键都将无效,所以很明显,必须对它们做些什么。 级联删除是一种可能的解决方案。 将外键设置为NULL
,从而使关系无效,是另一种可能的解决方案。
你的孩子 id 指的是一个组或一个对象的概念违反了任何参照完整性的概念。 关系数据库理论没有用处,也没有提供多态性。 一个键必须指代一种且仅一种实体。 如果没有,那么您就会开始遇到刚刚发现的问题,但更糟糕的是,您的数据库中没有任何参照完整性保证。 这不是一个很好的情况。
处理与不同类型实体的关系需求的方法是使用一组外键,每个可能的相关实体一个,其中只有一个可能是非空的。 所以,这是它的样子:
CREATE TABLE tree_relation (
parent_id INTEGER,
child_object_id INTEGER,
child_group_id INTEGER,
PRIMARY KEY (parent_id, child_object_id, child_group_id) );
ALTER TABLE tree_relation
ADD FOREIGN KEY (parent_id) REFERENCES group(id) ON DELETE CASCADE;
ALTER TABLE tree_relation
ADD FOREIGN KEY (child_object_id) REFERENCES object(id) ON DELETE CASCADE;
ALTER TABLE tree_relation
ADD FOREIGN KEY (child_group_id) REFERENCES group(id) ON DELETE CASCADE;
您需要做的就是确保只有child_object_id
、 child_group_id
是非空的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.