触发器内的函数 returns 错误值
Function returns bad value inside of a trigger
我有两个功能,return 物有所值。但是当我在触发器内部调用这些函数时,它们总是 returns 0 而不是好的值。
这些函数的 return 类型是 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=
and id_absence_type=
and id_year= );
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()
或 table remaining_absence_day
的第二个实例。然后您使用 search_path
的不同设置调用该函数。
您 运行 是否在同一会话中进行了比较?
- How does the search_path influence identifier resolution and the "current schema"
或者,由于您使用 AFTER
触发器:table absence
上可能有 其他触发器 修改 table 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 =
AND id_absence_type =
AND id_year =
);
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();
我有两个功能,return 物有所值。但是当我在触发器内部调用这些函数时,它们总是 returns 0 而不是好的值。
这些函数的 return 类型是 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=
and id_absence_type=
and id_year= );
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()
或 table remaining_absence_day
的第二个实例。然后您使用 search_path
的不同设置调用该函数。
您 运行 是否在同一会话中进行了比较?
- How does the search_path influence identifier resolution and the "current schema"
或者,由于您使用 AFTER
触发器:table absence
上可能有 其他触发器 修改 table 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 =
AND id_absence_type =
AND id_year =
);
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();