PostgreSQL:检查函数中是否有新的和旧的触发器

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

我想创建一个触发器来计算行数并更新其他表中的字段。我当前的解决方案适用于 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';

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

CREATE TRIGGER count_trigger
AFTER INSERT OR DELETE
ON source_table
FOR EACH ROW
EXECUTE PROCEDURE update_table_count();

当我执行 DELETE 语句时,出现以下错误:

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

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

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

感谢您的帮助

postgresql plpgsql database-trigger postgresql-9.5
2个回答
10
投票

使触发器函数根据触发器的触发方式执行不同操作的常用方法是通过 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;

不相关,但是:语言名称是一个标识符。不要使用单引号引用它。


1
投票

来自 PostgreSQL 的文档

数据类型RECORD;保存行级触发器中 INSERT/UPDATE 操作的新数据库行的变量。 此变量在语句级触发器和 DELETE 操作中为空

数据类型RECORD;保存旧数据库行的变量,用于行级触发器中的 UPDATE/DELETE 操作。 此变量在语句级触发器和 INSERT 操作中为 null。

因此,例如,如果 NEW 为 NULL,则在 DELETE 时调用触发器。

编辑 在回复 blissweb 评论时,假设它是一个
BEFORENOT 语句级触发器,这里有一个 plpgsql 代码示例:

... IF NEW IS NULL THEN -- Record is to be DELETEd. ELSEIF OLD IS NULL THEN -- Record is to be INSERTed. ELSE -- Record is to be UPDATEd. END IF; ...
    
© www.soinside.com 2019 - 2024. All rights reserved.