调用plpgsql函数时出错

时间:2014-10-23 11:58:07

标签: postgresql plpgsql dynamic-sql quoting

以下是我在function

中创建的PostgreSQL 9.2
CREATE OR REPLACE function fn_exp_settl_cr
(branchid int
 ,vrid int
 ,ddate date
 ,acid int
) 
returns 
TABLE ( trno character varying(15), trdate timestamp without time zone, netamt money, duedate 
        timestamp without time zone,tranid integer, acyrid integer, custrefno  
        charactervarying(26), orderdate timestamp without time zone) as $$
declare 
sql text;
begin
execute 'select string_agg(s.qry,'' UNION ALL '')  from (select ''SELECT 
         TrNo,TrDate,NetAmt,DueDate,TranId,AcYrId,custrefno,orderdate FROM '||t.relname||' WHERE 
         AdjInBill = false And  ExpSettled = false And (BranchID = 1) AND (VrId = 29) and   
         DueDate <= ''2014-07-24'' and AcId=76 '' qry from (select relname from 
         pg_stat_user_tables where relname ilike ''gtab09%'') t )s ' into sql;
execute sql;
end;
$$ language plpgsql

它成功创建,但在调用此函数时,即:

select * from fn_exp_settl_cr(1,2,'2014-07-24',4)

我收到以下错误:

  

错误:缺少FROM-clause条目表&#34; t&#34;第1行:   ... DueDate,TranId,AcYrId,custrefno,orderdate FROM&#39; || t.relname | ...

1 个答案:

答案 0 :(得分:2)

CREATE OR REPLACE function fn_exp_settl_cr(_branchid int, _vrid int
                                         , _ddate date, _acid int)
  RETURNS TABLE (
   trno character varying(15)
 , trdate timestamp
 , netamt money
 , duedate timestamp
 , tranid integer
 , acyrid integer
 , custrefno  character varying(26)
 , orderdate timestamp
) AS
$func$
BEGIN

RETURN QUERY EXECUTE (
   SELECT string_agg
            (format
               ($$SELECT TrNo,TrDate,NetAmt,DueDate,TranId,AcYrId
                        ,custrefno,orderdate
                  FROM   %I
                  WHERE  AdjInBill = false
                  AND    ExpSettled = false
                  AND    BranchID = $1
                  AND    VrId = $2
                  AND    DueDate <= $3
                  AND    AcId = $4
                $$
               ,t.relname
               )
            ,' UNION ALL '
            )
   FROM   pg_class t
   WHERE  t.relkind = 'r' -- ordinary table
   AND    t.relname ILIKE 'gtab09%'
   )
USING _branchid, _vrid, _ddate, _acid;

END
$func$ LANGUAGE plpgsql;

重点

  • 您的格式难以阅读,这可能是您无法找到问题的主要原因。

  • charactervarying(26)中的错字。修复:character varying(26)。不过,我只会使用varchartext

  • 您对多层引用感到困惑。修复方法是使用美元引用和format()来构建字符串。此外,可以简化一到两层。

  • 您实际上并未使用输入参数。可能是因为你遇到了困难,正在测试字面值。在此期间,我使用USING条款构建了这些内容。

  • 我建议不要使用与参数名称相同的标识符。这些在函数体中随处可见,并且容易导致命名冲突。前缀为'_'。

  • 你实际上没有归还任何东西。为此,请使用RETURN QUERY EXECUTE代替EXECUTE

为什么要从statistics view pg_stat_user_tables检索表名?从信息模式或目录表pg_class获取它更便宜,更可靠。改变了这一点。