PostgreSQL(Postgis)插入时的并行触发器

kknvjkwl  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(1)|浏览(180)

我有一个表如下表:

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)相对较新,因此这个任务给予我头疼。

  1. BEFORE触发记录2开始几毫秒的记录1 AFTER触发,但在IF条件下记录1未被提取。为什么?
    1.我如何才能实现这种“独特性”,基于非常接近的点之间的距离?
    1.是否排除约束索引?
kyxcudwk

kyxcudwk1#

如果记录2在记录1被插入之后但在它被提交之前到达,那么为2触发的触发器将不会看到记录1,并且将允许复制。未提交的记录不能被其他进程看到。
是的,EXCLUDE约束是解决方案。在这种情况下,2的“触发器”不需要遵循正常的用户可见性规则,因此它将检测与未提交记录1的可能冲突,并阻止直到解决提交或中止。

相关问题