我需要在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)
有人能让我知道我在这里缺少什么以及如何继续吗?任何提示都非常感谢!
答案 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 next
或return query
:
return next
,示例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
命令只有一种方式,可以从函数中返回一个标量值。还有其他像我上面演示的那个,还有更多: