将表名传递给函数并返回表

时间:2017-03-31 01:57:28

标签: postgresql plpgsql

我需要在DB的许多表(PostgreSQL 9.3.5)上运行相同的查询,并将表名作为参数传递给函数似乎是一件逻辑事情。阅读文档中的例子和众多的S.O.张贴,我仍然无法确定它。

使用这个最小的例子:

CREATE TABLE films (
code        char(5),
kind        varchar(10)
);
INSERT INTO films VALUES
('UA502', 'Comedy');

这个功能:

CREATE OR REPLACE FUNCTION foo(_t text)
RETURNS void AS  -- I know, void is not what I am after
$func$
BEGIN
   EXECUTE format('SELECT count(*) FROM %I', _t);
END
$func$  LANGUAGE plpgsql;

以下查询捕获了一些内容:

mydb=> SELECT foo('films');
 foo
-----
(1 row)

但是因为我想要检索一个表,所以我编辑了第二行并重新创建了这样的函数:

CREATE OR REPLACE FUNCTION foo(_t text)
RETURNS TABLE(count integer) AS
$func$
BEGIN
   EXECUTE format('SELECT count(*) FROM %I', _t);
END
$func$  LANGUAGE plpgsql;

然而,相同的查询没有捕获任何内容:

mydb=> SELECT foo('films');
foo
-----
(0 rows) 

有人能让我知道我在这里缺少什么以及如何继续吗?任何提示都非常感谢!

2 个答案:

答案 0 :(得分:4)

如果函数返回标量值,则必须包含return <expression>

  • 声明一个变量,
  • 为其指定一个值(在execute ... into ...的示例中),
  • return <expression>
  • 中使用它

示例:

drop function if exists foo(_t text);
create or replace function foo(_t text)
returns bigint as
$func$
declare
    res bigint;
begin
    execute format('select count(*) from %I', _t) into res;
    return res;
end
$func$ language plpgsql;

select foo('films');

如果函数返回表,则必须包含return nextreturn query

  • 为声明的返回表的列
  • 分配值
  • 使用return next
  • 在FROM子句中调用该函数,而不是在SELECT列表中调用。

示例1:

drop function if exists foo(_t text);
create or replace function foo(_t text)
returns table(count bigint) as
$func$
begin
   execute format('select count(*) from %I', _t) into count;
   return next;
end
$func$  language plpgsql;

select * from foo('films');

如果函数返回表格,您也可以使用return query

示例2:

drop function if exists foo(_t text);
create or replace function foo(_t text)
returns table(count bigint) as
$func$
begin
    return query
        execute format('select count(*) from %I', _t);
end
$func$  language plpgsql;

select * from foo('films');

答案 1 :(得分:4)

您需要使用EXECUTE的动态SQL,并且需要正确地转义标识符。你已经做对了。

您在如何返回值和@klin provides solutions for that时遇到问题。

要传递 表名 ,我建议使用regclass参数。而且,为简单起见,结果为OUT参数:

CREATE OR REPLACE FUNCTION f_count_rows(_tbl regclass, OUT _ct bigint)
  RETURNS bigint AS
$func$
BEGIN
   EXECUTE 'SELECT count(*) FROM ' ||  _tbl INTO _ct;
END
$func$  LANGUAGE plpgsql;

这样......

  • 您不需要手动转义表名,因为它已内置于类型转换中。

  • 最重要的是,您可以传递符合条件的表名,例如myschema.mytable,如果您通过了 失败 作为text,并使用quote_ident(_tbl)format('... %I' _tbl)在函数体中对其进行转义。将被解释为表名"myschema.mytable"。您必须单独传递模式和表名称才能使其正常工作。

  • OUT参数很方便,因为它替换了变量声明和RETURN命令。否则相当于。当函数到达控制结束时,将自动返回OUT参数的当前状态。

相关:

要明确: RETURN命令只有一种方式,可以从函数中返回一个标量值。还有其他像我上面演示的那个,还有更多: