我有两张表代表两种不同类型的图像。我使用PostGIS来表示这些图像的边界。以下是这些表的简化示例:
CREATE TABLE img_format_a (
id SERIAL PRIMARY KEY,
file_path VARCHAR(1000),
boundary GEOGRAPHY(POLYGON, 4326)
);
CREATE TABLE img_format_p (
id SERIAL PRIMARY KEY,
file_path VARCHAR(1000),
boundary GEOGRAPHY(POLYGON, 4326)
);
我还有一个交叉引用表,我想要包含彼此重叠的图像的所有ID。每当“A”类型的图像被插入到数据库中时,我想检查它是否与任何类型为“P”的现有图像重叠(反之亦然),并将相应的条目插入到img_a_img_p
交叉中参考表。该表应代表多对多关系。
我的第一直觉是编写一个触发器来管理这个img_a_img_p
表。我之前从未创造过触发器,所以让我知道这是否是一件愚蠢的事情,但它似乎对我有意义。所以我创建了以下触发器:
CREATE TRIGGER update_a_p_cross_reference
AFTER INSERT OR DELETE OR UPDATE OF boundary
ON img_format_p FOR EACH ROW
EXECUTE PROCEDURE check_p_cross_reference();
我遇到困难的部分是编写触发功能。我的代码是用Java编写的,我看到有像PL / pgSQL这样的工具,但我不确定这是不是我应该使用的,或者我是否需要其中一个特殊的附加组件。
基本上我需要触发器做的是每次将新图像插入img_format_a
或img_format_p
时更新交叉引用表。插入新图像时,我想使用像ST_Intersects
这样的PostGIS函数来确定新图像是否与其他表中的任何图像重叠。对于ST_INTERSECTS
返回true的每个图像对,我想在img_a_img_p
中插入一个新条目,其中包含两个图像的ID。有人可以帮我弄清楚如何编写这个触发器功能吗?这是一些伪代码:
SELECT * FROM img_format_p P
WHERE ST_Intersects(A.boundary, P.boundary);
for each match in selection {
INSERT INTO img_a_img_p VALUES (A.id, P.id);
}
答案 0 :(得分:4)
你可以在PL / pgSQL函数中包含通常的INSERT ... SELECT
成语,如下所示:
create function check_p_cross_reference() returns trigger as
$$
begin
insert into img_a_img_p (img_a_id, img_p_id)
select a.id, p.id
from img_format_a, img_format_p
where p.id = NEW.id
and ST_Intersects(a.boundary, p.boundary);
return null;
end;
$$ language plpgsql;
触发器有两个额外的变量,NEW
and OLD
:
新强>
数据类型RECORD;变量为行级触发器中的INSERT / UPDATE操作保存新数据库行。在语句级触发器和DELETE操作中,此变量为NULL。<强> OLD 强>
数据类型RECORD;变量在行级触发器中保存旧数据库行以进行UPDATE / DELETE操作。在语句级触发器和INSERT操作中,此变量为NULL。
因此,您可以使用NEW.id
来访问新的img_format_p
值。您(当前)can't use the plain SQL触发语言:
目前无法用纯SQL函数语言编写触发器函数。
但PL / pgSQL非常接近。这将作为AFTER INSERT触发器有意义:
CREATE TRIGGER update_a_p_cross_reference
AFTER INSERT
ON img_format_p FOR EACH ROW
EXECUTE PROCEDURE check_p_cross_reference();
可以使用foreign key on img_a_img_p
and a cascading delete处理删除。您也可以将触发器用于UPDATE:
CREATE TRIGGER update_a_p_cross_reference
AFTER INSERT OR UPDATE OF boundary
ON img_format_p FOR EACH ROW
EXECUTE PROCEDURE check_p_cross_reference();
但是您可能希望在插入新条目之前清除旧条目,例如:
delete from img_a_img_p where img_p_id = NEW.id;
在INSERT...SELECT
陈述之前。