PostgreSQL:检查触发器函数中的NEW和OLD

Fre*_*ete 2 postgresql plpgsql database-trigger postgresql-9.5

我想创建一个对行进行计数并更新另一个表中的字段的触发器。我当前的解决方案适用于INSERT语句,但是当我删除一行时失败。

我当前的功能:

 CREATE OR REPLACE FUNCTION update_table_count()
RETURNS trigger AS
$$
DECLARE updatecount INT;
  BEGIN
      Select count(*) into updatecount 
        From source_table 
       Where id = new.id;
      Update dest_table set count=updatecount 
       Where id = new.id;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';
Run Code Online (Sandbox Code Playgroud)

触发器是一个非常基本的触发器,看起来像。

CREATE TRIGGER count_trigger
AFTER INSERT OR DELETE
ON source_table
FOR EACH ROW
EXECUTE PROCEDURE update_table_count();
Run Code Online (Sandbox Code Playgroud)

当我执行DELETE语句时,会发生以下错误:

错误:记录“新”尚未分配

详细信息:尚未分配的记录的元组结构是不确定的。

我知道一个解决方案可能是只为DELETE创建一组触发器和函数,为INSERT语句创建一组触发器和函数。但是我想做得更优雅一些,并且想知道,是否有一种解决方案可以检查当前上下文中是否存在NEW或OLD并仅实现IF ELSE块。但我不知道如何检查此上下文相关项。

谢谢你的帮助

a_h*_*ame 5

根据触发方式如何,使触发函数执行不同操作的通常方法是通过TG_OP检查触发操作

CREATE OR REPLACE FUNCTION update_table_count()
RETURNS trigger AS
$$
DECLARE 
  updatecount INT;
BEGIN
  if tg_op = 'UPDATE' then 
    select count(*) into updatecount from source_table where id = new.id;
    update dest_table set count=updatecount where id = new.id;
  elsif tg_op = 'DELETE' then 
    ... do something else
  end if;
  RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

无关,但是:语言名称是一个标识符。不要用单引号引起来。