sql - 函数在触发器内部返回错误值

标签 sql postgresql plpgsql database-trigger

我有两个返回良好值的函数。但是当我在触发器内部调用这些函数时,它们总是返回 0 而不是正确的值。

这些函数的返回类型是real。直接和戏剧性的后果是触发器在调用时在表中插入了错误的值。

函数:

create or replace function get_remaining_hour(id_user_v integer,id_absence_v_type integer,id_year_v integer) returns real as
$BODY$
BEGIN
    return (select sum(number_hour) 
            from remaining_absence_day 
            where id_user= $1 
              and id_absence_type=$2 
              and id_year=$3 );
END;
$BODY$
LANGUAGE 'plpgsql' ;

触发器函数(为测试而修改!):

create  OR REPLACE  function update_absence() returns TRIGGER  AS
$BODY$
DECLARE
  old_number_hour real;
BEGIN
  old_number_hour:=get_remaining_hour(3,2,8);
  insert into debugging(col,val) values('old_number_hour', old_number_hour);
  return null;
END;
$BODY$
LANGUAGE 'plpgsql' ;

触发器定义:

drop trigger if exists update_absence on absence;
CREATE  TRIGGER update_absence
    after update of type,duration_hour,duration_day on absence
    for each ROW
    execute procedure update_absence();

最佳答案

提供的代码应该可以工作。

您看到 0 作为结果特别奇怪。如果在 remaining_absence_day 中找不到匹配的行,您将看到 NULL,而不是 0。但是,如果您在相同的环境中使用相同的参数调用该函数,您应该会看到相同的结果。

我能想到的剩下的可能解释:混淆了模式搜索路径。例如:您在不同的架构中有函数 get_remaining_hour() 或表 remaining_absence_day 的第二个实例。并且您使用 search_path 的不同设置来调用该函数。 您是否在同一 session 中进行了比较?

或者,由于您使用的是 AFTER 触发器:表 absence 上可能存在修改表 remaining_absence_day 的其他触发器 ,在您的触发器之前触发。

我所做的所有其他修改都是装饰性的或轻微的简化

CREATE OR REPLACE FUNCTION get_remaining_hour(id_user_v int
                                            , id_absence_v_type int
                                            , id_year_v int)
  RETURNS real AS
$func$
BEGIN
   RETURN (
   SELECT sum(number_hour) 
   FROM   remaining_absence_day  -- referencing the right table? see search_path
   WHERE  id_user         = $1 
   AND    id_absence_type = $2 
   AND    id_year         = $3
   );
END
$func$  LANGUAGE plpgsql STABLE;  -- don't quote the language name

CREATE OR REPLACE FUNCTION update_absence()
  RETURNS TRIGGER AS
$func$
BEGIN   
   INSERT INTO debugging(col, val)
   VALUES('old_number_hour', get_remaining_hour(3,2,8));  -- hard coded only for testing?
   RETURN null;  -- only good for AFTER trigger
END
$func$  LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS update_absence ON absence;
CREATE TRIGGER update_absence
AFTER UPDATE OF type, duration_hour, duration_day ON absence
FOR EACH ROW EXECUTE PROCEDURE update_absence();

关于sql - 函数在触发器内部返回错误值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39223746/

相关文章:

mysql - 按 groupby 计数的 sql 查询问题

postgresql - 使用 Postgres 在 docker 中上传 csv 文件

postgresql - sql语句确保postgres中的原子性

sql - 在尝试更改之前如何检查数据库中是否使用了行?

python - SQLAlchemy 和 Google Cloud Sql session 池

postgresql - 如何从作为表名的变量中选择 n Postgre >=9.2

PostgreSQL 触发器不返回任何内容

php - 加速此代码 - PHP/SQL - 短代码但目前需要非常长的时间

php - 由于时间戳 now(),SQL 插入忽略不起作用

java - 如何将相同的值写入2个数据库?