【问题标题】:How to pass a table name for a cursor as function parameter?如何将游标的表名作为函数参数传递?
【发布时间】:2016-10-24 07:59:25
【问题描述】:

在 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。我明白了,不允许将表名作为函数参数传递,允许休息(选择,投影)。

是否有其他方法可以实现这一目标?

【问题讨论】:

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


    【解决方案1】:

    在 SQL 命令中只能参数化值,而不是标识符或关键字。它目前仅适用于SELECT、INSERT、UPDATE 和DELETE 命令。详情:

    您需要在 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;
    

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

    【讨论】:

    • 我试过这个。实际上我想使用光标的输入(在声明块中)。
    • @Spike:我添加了另一个答案如何为此使用光标。
    • 工作正常。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多