我想知道我是否遗漏了一些明显的东西。我有一个定义表名的函数,然后在execute子句中查询该表。但是如果主表中没有数据(one_min,fifteen_min等),我会返回一个null_value_not_allowed异常,代码为22004.当我尝试处理异常的处理程序时,它似乎完全通过它并仍然死亡。我试着把更大的条件包裹起来,但仍然没有运气。
CREATE OR REPLACE FUNCTION loadresults(force_update boolean)
RETURNS date AS
$BODY$
declare
inter int;
startdate date;
table_name varchar(50);
BEGIN
select 1440 / avg(array_length(intervals,1))::int into inter from temptable;
Case inter
when 1 then
table_name := 'one_min';
when 15 then
table_name := 'fifteen_mins';
when 30 then
table_name := 'half_hour';
when 60 then
table_name := 'one_hour';
else
raise EXCEPTION 'I do not recognise the interval %', inter ;
end case;
SET CONSTRAINTS ALL DEFERRED ;
if force_update is true then
select min(sday) into startdate from temptable ;
else
begin
execute ' select max(sday) from ' || table_name
|| ' where (orgid,householdid) in
(select orgid, householdid from temptable limit 1 )'
into startdate ;
EXCEPTION when null_value_not_allowed then
select min(sday) into startdate from temptable;
end;
end if;
return startdate;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
鉴于所有表都存在且工作正常 - 该函数继续加载数据 - 当force_flag为真时它可以正常工作。
当force_update标志为false并且one_min表中没有数据时,我收到此错误:
ERROR: query string argument of EXECUTE is null
SQL state: 22004
Context: PL/pgSQL function loadresults(boolean) line 39 at EXECUTE statement
这指向execute语句,其中查询不会返回任何值。 任何想法为什么会发生?我宁愿在Postgres中保留错误处理而不是剩下的代码。
更新
我现在用execute this子句更新了execute子句中的查询:
execute ' select coalesce(res, tem) from ' ||
' (select max(sday) as res from ' || table_name || '
where (orgid,householdid) in (select orgid, householdid from temptable limit 1 )) t1,
(select min(sday) as tem from temptable) m ' into startdate ;
这似乎可以解决问题,因为没有引发异常。我仍然想了解为什么无法捕获异常。
答案 0 :(得分:3)
很奇怪,但似乎有两个null_value_not_allowed
例外(22004
和39004
)。
尝试通过他们的sqlstate捕获它,例如:
BEGIN
-- ...
EXCEPTION WHEN SQLSTATE '22004' THEN
-- ...
END;
或者,您可以获得相同的结果,并附加条件:
IF force_update OR table_name IS NULL THEN
SELECT min(sday) INTO startdate FROM temptable;
ELSE
EXECUTE 'select max(sday) from '
|| table_name
|| ' where (orgid,householdid) in (select orgid, householdid from temptable limit 1 )'
INTO startdate;
END IF;