PL / pgSQL触发阻止河流穿过另一条河流

时间:2022-07-19 22:47:14

I have to write a trigger to stop a river crossing another river. I'm really struggling with it and any help would be appreciated. myriver is the table containing all the information on the rivers. So upon insert of a new river if it crosses an existing river, I should receive an error. Here's what I have:

我必须写一个触发器来阻止河流穿过另一条河流。我真的很挣扎,任何帮助都会受到赞赏。 myriver是包含河流所有信息的表格。因此,如果插入一条新河,如果它穿过现有的河流,我应该收到错误。这就是我所拥有的:

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();

1 个解决方案

#1


You are using a column of the to-be-inserted/-updated row (NEW.the_geom) as a temporary variable. So you will either over-write that column variable (giving the new row a bogus value), or get an irrelevant result on your IF check (because NEW.the_geom had data in it anyway before the trigger was run).

您正在使用要插入/更新的行(NEW.the_geom)的列作为临时变量。所以你要么覆盖那个列变量(给新行一个虚假的值),要么在你的IF检查中得到一个不相关的结果(因为在运行触发器之前,NEW.the_geom中都有数据)。

Note also that Postgres, and pl/pgsql, is strictly typed, so you can't use an arbitrary value in an IF statement to see if it is "empty", like you would in a scripting language like PHP.

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

You need to either add a DECLARE block to give you a proper temporary variable, and check if it IS NULL; Or just use an EXISTS check directly:

您需要添加一个DECLARE块来为您提供适当的临时变量,并检查它是否为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;

#1


You are using a column of the to-be-inserted/-updated row (NEW.the_geom) as a temporary variable. So you will either over-write that column variable (giving the new row a bogus value), or get an irrelevant result on your IF check (because NEW.the_geom had data in it anyway before the trigger was run).

您正在使用要插入/更新的行(NEW.the_geom)的列作为临时变量。所以你要么覆盖那个列变量(给新行一个虚假的值),要么在你的IF检查中得到一个不相关的结果(因为在运行触发器之前,NEW.the_geom中都有数据)。

Note also that Postgres, and pl/pgsql, is strictly typed, so you can't use an arbitrary value in an IF statement to see if it is "empty", like you would in a scripting language like PHP.

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

You need to either add a DECLARE block to give you a proper temporary variable, and check if it IS NULL; Or just use an EXISTS check directly:

您需要添加一个DECLARE块来为您提供适当的临时变量,并检查它是否为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;