我正在编写一个绘图表面,其中包含元素和连接。
表面上我的两个表格如下:
CREATE TABLE element
(
elid character varying(60) NOT NULL,
data json,
surface_id character varying(60) NOT NULL,
type character varying,
CONSTRAINT element_primary_key PRIMARY KEY (elid),
)
CREATE TABLE connection
(
from_elid character varying(60) NOT NULL,
to_elid character varying(60) NOT NULL,
CONSTRAINT from_to_element_id PRIMARY KEY (from_elid, to_elid),
CONSTRAINT from_element_fk FOREIGN KEY (from_elid)
REFERENCES element (elid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT to_element_fk FOREIGN KEY (to_elid)
REFERENCES element (elid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
)
如果我删除表面上的元素,它也会删除相应的连接,这由connection
约束表示。
在这种情况下,我检查具有相同surface_id
的所有元素,并删除那些缺失的元素(以及它们的连接)。
但是如何在绘图表面上删除时明确删除连接?由于from_elid
和to_elid
仍然存在于表element
?
编辑:为了保存绘图表面,客户端将它们之间的所有元素和连接发送到服务器。
数据库中的示例数据:
-------------------------------- ---------------------
|element | |connection |
-------------------------------- ---------------------
|elid | data |surface_id |type | |from_elid |to_elid |
--------------------------------- ---------------------
|e1 |{} |s1 |xxx | |e1 |e2 |
|e2 |{} |s1 |xxx | |e2 |e3 |
|e3 |{} |s1 |xxx | |e3 |e4 |
|e4 |{} |s1 |xxx | |.. |.. |
|e5 |{} |s2 |xxx | |e5 |e6 |
|e6 |{} |s2 |xxx | |e6 |e7 |
|.. |.. |.. |... | |.. |.. |
--------------------------------- ---------------------
客户发送的示例数据:
{
surface_id: 's1',
elements:['e1','e2','e3','e4'],
connections:[
{from:'e2', to:'e3'},
{from:'e3', to:'e4'}
]
}
在示例数据中,e1
和e2
之间的关联缺失,这意味着它已在绘图表面上删除surface_id
=' s1'并且必须从表connection
中删除。如何使用给定数据实现这一点并且不使用surface_id
=' s2'?
答案 0 :(得分:1)
但是如何在绘图表面上删除时明确删除连接?由于from_elid和to_elid仍然存在于表元素
中
您误解了外键是如何工作的。从connection
到element
的外键表示如果插入连接,则元素必须。 不要求每个元素都存在连接。
因此,您可以随时从connection
表中删除行。只要至少有一个使用该元素的连接,您就无法从element
表中删除行。
修改
如果您的程序只获得“幸存”连接,您可以使用提供的信息删除过时的连接
假设您有三个连接,并且您不知道哪些是新的,哪些不是:
首先需要删除不存在的:
delete from connection
where (from_elid, to_elid) not in ( ('e2', 'e3'), ('e3','e4'), ('e4','e1') )
and exists (select 1
from element e
where e.elid in (connection.from_elid, connection.to_elid)
and e.surface_id = 's1');
除了in
子句中的元素之外,这将删除表面s1上元素的所有连接。
现在你需要从connection
表中不存在的那个列表中插入那些连接 - 基本上是一个条件插入。这可以使用insert .. select
:
insert into connection (from_elid, to_elid)
select *
from (
values ('e2', 'e3'), ('e3','e4'), ('e4','e1')
) as t (from_elid, to_elid)
where not exists (select *
from connection c
where (t.from_elid, t.to_elid) = (c.from_elid, c.to_elid));
您需要在多用户环境中正确处理唯一键冲突,因为其他事务可能会插入相同的信息。
SQLFiddle示例:http://sqlfiddle.com/#!15/64e7d/1
答案 1 :(得分:0)
但是如何在删除时明确删除连接 绘图表面?
你的意思是你想删除元素表中引用的elid条目后连接表中的那些外键条目?
在任何情况下,如果DDL不允许你想要实现的目标,你可以考虑使用BEFORE DELETE或AFTER DELETE之类的触发器,这样你就可以先清理元素表,然后再清理连接表或连接表。元素表。