如何将游标的表名作为函数参数传递?

时间:2016-06-22 11:39:55

标签: postgresql cursor plpgsql postgresql-9.1 dynamic-sql

在PostgreSQL 9.1中,我需要将一个表名作为参数传递给我在函数中使用的函数 - 然后调用函数:

select myfunction('tableA');

或:

select myfunction('tableB')

我试过这个:

 create or replace function myfunction(sid text) 
 returns integer as $BODY$
 declare
      bids cursor is select id from sid; --line 4
 begin
      for bid in bids loop
          --some logic
      end loop;
      return 1;
 end;
 $BODY$
 language plpgsql volatile;

我得到了error on line 4。我明白了,它不允许将表名作为函数参数传递给它允许休息(选择,投影)。

是否有替代方案可以实现这一目标?

1 个答案:

答案 0 :(得分:3)

只能在SQL命令中参数化值,而不能在标识符或关键字中参数化。它目前仅适用于SELECTINSERTUPDATEDELETE命令。详细说明:

您需要在plpgsql中使用EXECUTE的动态SQL 将它与FOR循环的隐式游标相结合,这通常比显式游标更简单,更快。 Instructions in the manual.

我还建议使用regclass参数安全地传递有效的表名

CREATE OR REPLACE FUNCTION myfunction(_tbl regclass) 
  RETURNS int  AS
$func$
DECLARE
   bid integer;  -- appropriate data type!
BEGIN
   FOR bid IN EXECUTE
      'SELECT id FROM ' || _tbl
   LOOP
      -- statements can use bid
      RAISE NOTICE '%', bid;
   END LOOP;

   RETURN 1;
END
$func$  LANGUAGE plpgsql;

呼叫:

SELECT myfunction('tableA');  -- careful: case sensitive!

更多解释:

通常,有一个更快的基于集合的解决方案,根本不需要循环。

如果您肯定需要光标,请声明 未绑定光标 并使用OPEN FOR EXECUTE打开它:

CREATE OR REPLACE FUNCTION myfunction(_tbl text)  -- could be regclass again
  RETURNS int AS
$func$
DECLARE
   _bids refcursor;
   _rec  record;
BEGIN
   OPEN _bids FOR EXECUTE 'SELECT id FROM ' || quote_ident(_tbl);  -- text must be escaped

   LOOP
      FETCH NEXT FROM _bids INTO _rec;
      EXIT WHEN _rec IS NULL;

      -- some logic
      RAISE NOTICE '%', _rec.id;
   END LOOP;

   RETURN 1;
END
$func$  LANGUAGE plpgsql;

同一个电话。这个密切相关的答案的更多细节: