【问题标题】:Before insert trigger to replace new data postgres在插入触发器之前替换新数据 postgres
【发布时间】:2018-12-30 00:22:47
【问题描述】:

我有一个包含两个数据列的表:col1 和 col2。 Col1 是文本字段,col2 是时间。 Col1 是必需的,col2 不是,所以它应该有一个默认值 null。我使用 pgAdmin,这对我来说是全新的,就像 sql trigger 一样。我有如下触发函数代码:

CREATE OR REPLACE FUNCTION schema.table_replace()
  RETURNS trigger AS
  LANGUAGE 'plpgsql';
$BODY$
BEGIN
    (CASE
        WHEN NEW.col1='111' THEN NEW.col1='aaa'
        WHEN NEW.col1='222' THEN NEW.col1='bbb'
        WHEN NEW.col1='333' THEN NEW.col1='ccc'
        ELSE NEW.col1='error'
    END);
return NEW;
END;
$BODY$

这可能是之前的触发器(应该只影响当前值,而不是所有行):

CREATE TRIGGER schema.table_replace
  BEFORE INSERT
  ON schema.table
  EXECUTE PROCEDURE schema.table_replace();

说实话,我对pgAdmin一无所知,它似乎比编写代码并使用查询工具运行它要复杂得多。问题是处理没有第二个值的情况(它是可选的),在这种情况下,该行的 col2 应该保持不变,并且 SQL 代码也会返回错误。 您能否提供一些帮助以使其运行并创建函数和触发器? 谢谢。

【问题讨论】:

    标签: postgresql plpgsql database-trigger


    【解决方案1】:

    CASE 作为控制结构用END CASE 关闭(而表达式只用END 关闭)。并且分支中有语句,需要以分号结束。

    您的LANGUAGE 也放错了位置。那属于最后。而且你不需要单引号。

    col2 不为空时,您可以使用IF 进行替换。

    CREATE OR REPLACE FUNCTION schema.table_replace()
                               RETURNS trigger AS
    $BODY$
    BEGIN
      IF NEW.col2 IS NOT NULL THEN
        CASE
          WHEN NEW.col1 = '111' THEN
            NEW.col1 = 'aaa';
          WHEN NEW.col1 = '222' THEN
            NEW.col1 = 'bbb';
          WHEN NEW.col1 = '333' THEN
            NEW.col1 = 'ccc';
          ELSE
            NEW.col1 = 'error';
        END CASE;
      END IF;
    
      RETURN NEW;
    END;
    $BODY$
    LANGUAGE plpgsql;
    

    您还需要将触发器声明为FOR EACH ROW 触发器,NEW 才能工作。

    并且触发器名称不能是模式限定的。

    CREATE TRIGGER table_replace
                   BEFORE INSERT
                   ON schema.table
                   FOR EACH ROW
                   EXECUTE PROCEDURE schema.table_replace();
    

    【讨论】:

    • 它创建了我需要的函数和触发器。现在的问题:如果我运行以下命令,我会收到以下错误: INSERT INTO schema.table (col1) VALUES ('111');错误:尚未分配记录“新”详细信息:尚未分配记录的元组结构是不确定的。上下文:PL/pgSQL 函数 schema.table_replace() 第 3 行在 CASE SQL 状态:55000 有什么想法吗?
    【解决方案2】:

    您的示例的主要问题是您的 CREATE TRIGGER 语句中缺少 FOR EACH ROW 子句。如果没有此子句,则创建的触发器是具有不同行为的语句触发器。您的任务可以通过 SQL 函数式CASE 语句来解决。

    CREATE OR REPLACE FUNCTION schema.table_replace()
    RETURNS trigger AS
    LANGUAGE 'plpgsql';
    $BODY$
    BEGIN
      IF NEW.col2 NOT NULL THEN
        NEW.col1 := CASE NEW.col1
                         WHEN '111' THEN 'aaa'
                         WHEN '222' THEN 'bbb'
                         WHEN '333' THEN 'ccc'
                         ELSE 'error' END CASE;
      END IF;
      RETURN NEW;
    END;
    $BODY$
    

    【讨论】:

    • RETURN NEW 帮助了我!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    相关资源
    最近更新 更多