CREATE OR REPLACE FUNCTION getParentLtree(parent_id bigint, tbl_name varchar)
RETURNS ltree AS
$BODY$
DECLARE
parent_ltree ltree;
BEGIN
-- This works fine:
-- select into parent_ltree l_tree from tbl1 where id = parent_id;
EXECUTE format('select into parent_ltree l_tree from %I
where id = %I', tbl_name,parent_id);
RETURN parent_ltree;
END;
$BODY$ LANGUAGE plpgsql;
上述功能有两个问题:
parent_id
是integer
,但会被引号替换? int
变量的正确格式说明符是什么?select into
不适用于EXECUTE
?如何使上面的注释查询使用表名传递?答案 0 :(得分:10)
这会更短,更快,更安全:
CREATE OR REPLACE FUNCTION get_parent_ltree(parent_id bigint, tbl_name regclass
, OUT parent_ltree ltree) AS
$func$
BEGIN
EXECUTE format('SELECT l_tree FROM %s WHERE id = $1', tbl_name)
INTO parent_ltree
USING parent_id;
END
$func$ LANGUAGE plpgsql;
最重要的是,使用USING
clause of EXECUTE
作为参数值。不要将它们转换为text
,连接并解释它们。这样会更慢,容易出错。
通常,您会使用%I
specifier with format()
作为表名等标识符。但是有一种更好的方法:使用regclass
object-identifier type。详情:
Table name as a PostgreSQL function parameter
使用OUT
parameter来简化代码。表现是一样的。
不要在Postgres中使用不带引号的CaMeL案例标识符,例如getParentLtree
。 Details in the manual.
答案 1 :(得分:3)
对字符串使用%s
。 %I
用于标识符:
select format('select into parent_ltree l_tree from %I where id = %s', 'tbl1', 1);
format
---------------------------------------------------------
select into parent_ltree l_tree from tbl1 where id = 1
http://www.postgresql.org/docs/current/static/functions-string.html#FUNCTIONS-STRING-FORMAT
PL / pgSQL的select into
与Postgresql的select into
不同。请改为使用create table as
:
create table parent_ltree as
select l_tree
from tbl1
where id = 1
http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW
提示:请注意,使用INTO对SELECT的这种解释与PostgreSQL的常规SELECT INTO命令完全不同,其中INTO目标是新创建的表。如果要从PL / pgSQL函数内的SELECT结果创建表,请使用语法CREATE TABLE ... AS SELECT。
select into
语句中的execute
变量:
EXECUTE format('select l_tree from %I where id = %s', tbl_name,parent_id)
into parent_ltree;