当我尝试创建触发器时,PostgreSQL的语法错误。

问题描述 投票:0回答:1

我想在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。

sql postgresql plpgsql database-trigger
1个回答
1
投票

这是基于 a_horse_with_no_names 回答,因为它会抛出一个错误。

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

我还不能评论,所以才把这个作为答案贴出来。


2
投票

你的代码中存在多个错误。

  • IS NOT 不是一个有效的表达式,你需要 IS NOT NULL.
  • BEGINreturns 句不得 ;
  • 你忘了将函数体用字符串括起来(如果你使用了 美元报价
  • 你也不需要一个不必要的(额外的) 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();
© www.soinside.com 2019 - 2024. All rights reserved.