【问题标题】:syntax Error in PostgreSQL when I try to create Trigger当我尝试创建触发器时 PostgreSQL 中的语法错误
【发布时间】:2020-09-06 11:44:18
【问题描述】:

我想在 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 错误:“DECLARE”处或附近的语法错误 第 3 行:声明 old_id INTEGER;

【问题讨论】:

  • 你得到的错误是什么?
  • 语法错误:7 错误:“DECLARE”第 3 行或附近的语法错误:DECLARE old_id INTEGER;
  • 函数体(从DECLAREEND)必须是字符串字面量,即用'$$括起来。

标签: sql postgresql plpgsql database-trigger


【解决方案1】:

您的代码中有多个错误:

  • IS NOT 不是您需要的有效表达式 IS NOT NULL
  • BEGINreturns 子句之后不能有;
  • 你忘了把函数体封装成一个字符串(如果你使用dollar quoting这样更容易写
  • 如果您将其设为before 触发器,您也不需要不必要的(附加)UPDATE
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();

【讨论】:

    【解决方案2】:

    这是基于a_horse_with_no_names answer,因为它会抛出错误。

    ERROR: statement trigger's WHEN condition cannot reference column values

    您需要添加FOR EACH ROW,否则条件触发器将不起作用。

    如果两者都没有指定,则默认为 FOR EACH STATEMENT。

    语句级触发器也可以有 WHEN 条件,尽管该功能对它们不是那么有用,因为条件不能引用表中的任何值。

    See here

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

    我还不能发表评论,这就是我将其发布为答案的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-20
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      • 2012-07-27
      • 1970-01-01
      相关资源
      最近更新 更多