我想在PostgreSQL中创建触发器。
逻辑非常简单。
我需要触发器,如果published_at更新了并且written_at为空,则将published_at设置为written_at。
我写了这个,但是失败了。有人有什么办法吗?
CREATE function setWrittenAt() RETURNS trigger;
AS
DECLARE old_id INTEGER;
BEGIN ;
old_id = OLD.id
IF NEW.published_at IS NOT and NEW.written_at IS null
THEN
UPDATE review SET NEW.written_at = NEW.published_at where id = old_id;
END IF ;
RETURN NEW;
END;
LANGUAGE plpgsql;
CREATE TRIGGER update_written_at
AFTER UPDATE OF published_at ON review
WHEN (OLD.published_at IS DISTINCT FROM NEW.published_at)
EXECUTE PROCEDURE setWrittenAt();
错误。
语法错误。7 ERROR: 语法错误在 "DECLARE "行3附近:DECLARE old_id INTEGER。
这是基于 a_horse_with_no_name
s 回答,因为它会抛出一个错误。
ERROR: statement trigger's WHEN condition cannot reference column values
你需要添加 FOR EACH ROW
,否则条件触发器将无法工作。
如果两者都没有指定,则默认为FOR EACH STATEMENT。
语句级触发器也可以有WHEN条件,尽管这个功能对它们来说不是那么有用,因为条件不能引用表中的任何值。
CREATE TRIGGER update_written_at
BEFORE UPDATE OF published_at ON review
FOR EACH ROW
WHEN (OLD.published_at IS DISTINCT FROM NEW.published_at)
EXECUTE PROCEDURE setWrittenAt();
我还不能评论,所以才把这个作为答案贴出来。
你的代码中存在多个错误。
IS NOT
不是一个有效的表达式,你需要 IS NOT NULL
. BEGIN
和 returns
句不得 ;
UPDATE
如果你把它作为 before
触发CREATE function setwrittenat()
RETURNS trigger
AS
$$
BEGIN
IF NEW.published_at IS NOT NULL and NEW.written_at IS null THEN
NEW.written_at := = NEW.published_at; --<< simply assign the value
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
然后用 BEFORE
触发。
CREATE TRIGGER update_written_at
BEFORE UPDATE OF published_at ON review
WHEN (OLD.published_at IS DISTINCT FROM NEW.published_at)
FOR EACH ROW
EXECUTE PROCEDURE setWrittenAt();