create or replace function pd.check(
interval_ text[])
returns void as
$BODY$
BEGIN
EXECUTE '
drop table if exists check_;
create temp table check_
as
(
select unnest(' || interval_ || ')
) ;
';
END;
$BODY$
LANGUAGE PLPGSQL volatile;
我正在以
运行它select pd.check(ARRAY['2','3','4']);
它给了我一个错误:
运算符不是唯一的:未知||文本[]
提示:无法选择最佳候选运营商。您可能需要添加显式类型转换。
答案 0 :(得分:2)
假设当前的Postgres 9.6,你的功能将如下:
CREATE OR REPLACE FUNCTION pd.check(interval_ text[])
RETURNS void AS
$func$
BEGIN
EXECUTE '
DROP TABLE IF EXISTS pg_temp.check_;
CREATE TEMP TABLE check_ AS
SELECT unnest($1)'
USING $1; -- pass as value
END
$func$ LANGUAGE plpgsql;
您可以将参数值连接为字符串,但是您需要显式类型转换(因为连接无类型字符串文字和text[]
对Postgres来说是不明确的,它可能产生text
或text[]
,因此错误!)并转义特殊字符以使其工作。 quote_literal()
同时执行:quote_literal(interval_)
。不过, 不 。
而是将参数传递为 值 ,而不是字符串。这样更快,更安全,并避免出现任何此类错误
请注意,命令字符串中的$1
是指USING
子句提供的第一个表达式,而不是函数参数。 $1
的第二个实例实际上是指函数参数(不同的范围!)。
注意,这种将值传递给DML语句的优越方式在这里起作用,因为它是包含的SELECT
语句的一部分,但不适用于其他实用程序命令。详细说明:
drop table check_;
为 危险 。显然你想要定位临时表。但如果不存在,则search_path中的下一个同名表将被删除。潜在的灾难性损害。要定位临时表而不是其他目标,使用伪名称pg_temp
进行架构限定。
CREATE TABLE AS
围绕以下SELECT
命令不需要括号。
VOLATILE
是默认设置(对于此功能是正确的),我省略了噪音。
在这种特殊情况下,您不需要动态SQL。见@klin's answer。但EXECUTE
仍然是计划缓存无法获得的查询的理想选择。
答案 1 :(得分:1)
您不需要动态SQL(执行):
create or replace function pd.check(interval_ text[])
returns void as
$body$
begin
drop table if exists check_;
create temp table check_
as select unnest(interval_);
end;
$body$
language plpgsql volatile;
测试:
select pd.check(array['2','3','4']);
select * from check_;
unnest
--------
2
3
4
(3 rows)
答案 2 :(得分:1)
这与其他答案类似,但你真的不应该使用RETURNS VOID;你应该从函数本身返回一个集合。
[["2017/04/23", 972.5], ["2017/04/30", 2049],...
我做出的其他改变: