无法在postgresql 9.3中捕获null_value_not_allowed异常

时间:2014-03-10 16:35:46

标签: postgresql exception-handling plpgsql

我想知道我是否遗漏了一些明显的东西。我有一个定义表名的函数,然后在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 ;

这似乎可以解决问题,因为没有引发异常。我仍然想了解为什么无法捕获异常。

1 个答案:

答案 0 :(得分:3)

很奇怪,但似乎有两个null_value_not_allowed例外(2200439004)。

尝试通过他们的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;