Sql 两个递归多对多关系之间的约束
我有以下表格用于创建任意数量的不同类型的项目Sql 两个递归多对多关系之间的约束,sql,postgresql,many-to-many,data-modeling,Sql,Postgresql,Many To Many,Data Modeling,我有以下表格用于创建任意数量的不同类型的项目 CREATE TABLE item_types ( id SERIAL, PRIMARY KEY (id) -- Other columns omitted ); CREATE TABLE items ( id SERIAL, itemtype integer NOT NULL, PRIMARY KEY (id), FOREIGN KEY (itemtype) REFERENCES item_
CREATE TABLE item_types (
id SERIAL,
PRIMARY KEY (id)
-- Other columns omitted
);
CREATE TABLE items (
id SERIAL,
itemtype integer NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (itemtype) REFERENCES item_types (id)
-- Other columns omitted
);
items
表有一个称为item\u relationship
的递归多对多关系
CREATE TABLE item_relationships (
itemid1 integer,
itemid2 integer,
PRIMARY KEY (itemid1, itemid2),
FOREIGN KEY (itemid1) REFERENCES items (id),
FOREIGN KEY (itemid2) REFERENCES items (id)
);
item\u-types
表有一个递归的多对多关系,称为item\u-relationship\u-types
CREATE TABLE item_relationship_types (
type1 integer,
type2 integer,
PRIMARY KEY (type1, type2),
FOREIGN KEY (type1) REFERENCES item_types (id),
FOREIGN KEY (type2) REFERENCES item_types (id)
);
现在,我想做的是以某种方式设置一个约束,即您不能意外地创建一个无效的项目关系
,即在任何项目关系类型
中都找不到项目的项目类型
。我有两个问题
- 这并不完美,但似乎有效
一种可能的方法是使用代理主键扩展
项关系类型表:
CREATE TABLE item_relationship_types (
id integer SERIAL,
type1 integer,
type2 integer,
PRIMARY KEY (id),
UNIQUE (type1, type2),
FOREIGN KEY (type1) REFERENCES item_types (id),
FOREIGN KEY (type2) REFERENCES item_types (id)
);
然后将指向该代理键的外键添加到item_relationships
表中:
CREATE TABLE item_relationships (
itemid1 integer,
itemid2 integer,
type_rel_id integer not null,
PRIMARY KEY (itemid1, itemid2),
FOREIGN KEY (itemid1) REFERENCES items (id),
FOREIGN KEY (itemid2) REFERENCES items (id),
FOREIGN KEY (type_rel_id) REFERENCES item_relationship_types (id)
);
您还需要创建一个触发器,防止在项目关系
表中输入type\u rel\u id
值,该值指向项目关系
表中类型与这两个项目不相关的项目。注:此处不涉及递归;这是一种模型->实例继承模式,“递归”到底是什么意思?例如,当表项关系类型
具有以下记录时:(1,2)、(2,3)、(3,4)
,是否意味着类型1不仅与类型2相关,而且与类型3和4相关?@wildplasser感谢您的澄清。@kordirko在您的示例1中间接与3和4相关,但在(1,3)和(1,4)类型的项目之间创建项目_关系应该是不可能的。仅在您列出的记录之间。如果有人从项目关系类型
中删除记录,而没有从项目关系
中删除相应的行,该怎么办?完整性将被破坏。是的,你也需要处理那个案子。(不幸的是,这里不可能进行级联)@D4rt我回滚到原始版本。它似乎是正确的。您正在将项目(id)
与项目类型(id)
进行比较。items(id)
中的值范围为101到109,而item_类型(id)
中的值范围为1到9,因此它们从不匹配。您的代码在两个插入上都失败。这里,第一对插入成功,第二对失败,正如预期的那样。我会再查一遍。我试过扳机的变体,但它被证明太慢了。我扩展了您的想法,没有创建代理键,而是将type1
和type2
从item\u relationship\u types
直接添加到item\u relationships
。在item\u关系中
我添加了外键(type1,itemid1)引用items(itemtype,id)
,对于type2
和itemid2
也一样。然后我添加了外键(type1,type2)引用项\关系\类型(type1,type2)
。这有效地解决了约束问题,但不得不将type1
和type2
添加到item\u关系
中会让人感觉不舒服。对这个解决方案有什么想法吗?
CREATE TABLE item_relationships (
itemid1 integer,
itemid2 integer,
type_rel_id integer not null,
PRIMARY KEY (itemid1, itemid2),
FOREIGN KEY (itemid1) REFERENCES items (id),
FOREIGN KEY (itemid2) REFERENCES items (id),
FOREIGN KEY (type_rel_id) REFERENCES item_relationship_types (id)
);