我有一个表如下表:
CREATE TABLE pois (
id bigserial NOT NULL,
name int8 NOT NULL,
point point.geometry(point) NOT NULL
);
我想让pois唯一的ST_DISTANCE < 0.00001。我的意思是:
插入2条记录:
INSERT INTO pois (id,"name",point) VALUES
(1, 'Name 1', 'SRID=4326;POINT (14.071422731481 50.142209143518)');
INSERT INTO pois (id,"name",gps) VALUES
(1, 'Name 2', 'SRID=4326;POINT (14.071422781481 50.142209142518)');
你可以看到,这两个记录的点非常接近。这些都是实际上相同的位置,但保存有轻微的gps坐标差异(可以是几米)。
这些记录可以作为一个BATCH或单个事务或一个接一个地插入。
我希望能够“抓住”这样的重复。名称% 2应被丢弃而不保存。
我现在尝试的是使用BEFORE INSERT和AFTER INSERT触发器(PER ROW):
CREATE OR REPLACE FUNCTION check_duplicates()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
RAISE NOTICE 'New: %', NEW.name;
if EXISTS (
select * FROM pois
WHERE
ST_Distance(point, ST_SetSRID(NEW.point, 4326)) < 0.00001
)
then
RAISE NOTICE 'New: % exists - skip!', NEW.name;
RETURN NULL;
else
RAISE NOTICE 'New: % unique - save!', NEW.name;
RETURN NEW;
end if;
end; $function$;
当出现两条记录时(细化日志):
BEFORE TRIGGER: New Name 1
BEFORE TRIGGER: New Name 1 - unique - save!
. record 1 saved and AFTER trigger raised notification,so I can see in the logs the order.然后,记录2在毫秒之后出现:
BEFORE TRIGGER: New Name 2
BEFORE TRIGGER: New Name 2 - unique - save!
但是为什么呢?Rercord 2应该检测记录1,它已经保存在DB中,并且它们之间的距离< 0.00001,所以记录2实际上是记录1的重复,我希望看到:
触发前:新名称2 -存在-跳过!
我也试着用AFTER触发器。保存条件,但如果存在-
由于我对RDBs(Postgis)相对较新,因此这个任务给予我头疼。
- BEFORE触发记录2开始几毫秒的记录1 AFTER触发,但在IF条件下记录1未被提取。为什么?
1.我如何才能实现这种“独特性”,基于非常接近的点之间的距离?
1.是否排除约束索引?
1条答案
按热度按时间kyxcudwk1#
如果记录2在记录1被插入之后但在它被提交之前到达,那么为2触发的触发器将不会看到记录1,并且将允许复制。未提交的记录不能被其他进程看到。
是的,EXCLUDE约束是解决方案。在这种情况下,2的“触发器”不需要遵循正常的用户可见性规则,因此它将检测与未提交记录1的可能冲突,并阻止直到解决提交或中止。