RAF*_*FIQ 6 postgresql string-concatenation dynamic-sql plpgsql
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;
Run Code Online (Sandbox Code Playgroud)
上述功能有2个问题:
parent_id是integer,但它会被替换引号?int变量的正确格式说明符是什么?select into不起作用EXECUTE?如何使上面的注释查询使用表名传递?Erw*_*ter 12
这将更短,更快,更安全:
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;
Run Code Online (Sandbox Code Playgroud)
最重要的是,使用for参数值的USING子句EXECUTE.不要将它们转换为text,连接并解释它们.这将是更慢和容易出错的.
通常,您将使用%I带有format()标识符的说明符,例如表名.但是有一种更好的方法:使用regclass对象标识符类型.详细信息:
表名作为PostgreSQL函数参数
使用OUT参数来简化代码.表现是一样的.
不要像getParentLtreePostgres中那样使用不带引号的CaMeL案例标识符.手册中的详细信息.
使用%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
Run Code Online (Sandbox Code Playgroud)
http://www.postgresql.org/docs/current/static/functions-string.html#FUNCTIONS-STRING-FORMAT
PL/pgSQLselect into与 Postgresql 的select into. 改用create table as:
create table parent_ltree as
select l_tree
from tbl1
where id = 1
Run Code Online (Sandbox Code Playgroud)
http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW
提示:请注意,SELECT with INTO 的这种解释与 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;
Run Code Online (Sandbox Code Playgroud)