我必须写一个触发器来阻止一条河流穿过另一条河流。我真的很挣扎,任何帮助将不胜感激。 myriver 是包含河流所有信息的表。因此,如果新河流的 insert 穿过现有河流,我应该收到错误消息。这是我所拥有的:

CREATE FUNCTION river_check() RETURNS TRIGGER AS $river_check$
BEGIN

-- Check that gid is given
IF NEW.gid IS NULL THEN
   RAISE EXCEPTION 'river gid cannot be null';
END IF;

NEW.the_geom = (SELECT r.the_geom FROM myriver as r
    WHERE ST_CROSSES(NEW.the_geom, r.the_geom));

IF NEW.the_geom THEN
    RAISE EXCEPTION 'a river cannot cross another river';
END IF;

RETURN NEW;

END;
$river_check$ LANGUAGE plpgsql;

-- Function river_check is linked to a TRIGGER of same name:
CREATE TRIGGER river_check
BEFORE INSERT OR UPDATE ON myriver
FOR EACH ROW EXECUTE PROCEDURE river_check();

最佳答案

您正在使用要插入/更新的行 ( NEW.the_geom ) 的列作为临时变量。因此,您要么覆盖该列变量(为新行提供一个虚假值),要么在 IF 检查中得到不相关的结果(因为 NEW.the_geom 在触发器运行之前无论如何都包含数据)。

另请注意,Postgres 和 pl/pgsql 是严格类型化的,因​​此您不能在 IF 语句中使用任意值来查看它是否为“空”,就像在 PHP 等脚本语言中一样。

您需要添加 a DECLARE block 以提供适当的临时变量,并检查它是否为 IS NULL ;或者直接使用 EXISTS 检查:

IF EXISTS (
    SELECT r.the_geom FROM myriver as r
    WHERE ST_CROSSES(NEW.the_geom, r.the_geom)
)
THEN
    RAISE EXCEPTION 'a river cannot cross another river';
END IF;

10-08 03:29