PL/pgSQL 中的 EXECUTE...USING 中忽略了 USING 部分
Posted
技术标签:
【中文标题】PL/pgSQL 中的 EXECUTE...USING 中忽略了 USING 部分【英文标题】:USING section ignored in EXECUTE...USING in PL/pgSQL 【发布时间】:2014-05-21 08:36:59 【问题描述】:我尝试通过 EXECUTE..USING 动态创建一个序列,但将参数传递给它时遇到问题。根据documentation,我理解正确的形式应该是这样的:
CREATE OR REPLACE FUNCTION create_dyn_seq( /* some params */ )
RETURNS void AS $$
DECLARE
_seq_name text;
_min integer;
_max integer;
BEGIN
/*
some code assigning the variables
sample values:
_seq_name := 'hu01/1/0_seq';
_min := 101;
_max := 500;
*/
EXECUTE 'CREATE SEQUENCE "' || _seq_name || '" MINVALUE $1 MAXVALUE $2 '
USING _min::INT, _max::INT;
RETURN;
END;
$$ LANGUAGE plpgsql;
我添加了引号,_seq_name 本身似乎很好。但是,当我插入这些值时,会引发以下错误:
ERROR: syntax error at or near "$1"
LINE 1: CREATE SEQUENCE "hu01/1/0_seq" MINVALUE $1 MAXVALUE $2
我还尝试了 EXECUTE 的另一种语法,建议 here:
EXECUTE
'CREATE SEQUENCE "' || _seq_name || '" MINVALUE ' || $1 || ' MAXVALUE ' || $2
USING _min::INT, _max::INT;
现在错误不同了:
ERROR: syntax error at or near "hu01"
LINE 1: CREATE SEQUENCE "hu01/1/0_seq" MINVALUE hu01 MAXVALUE 1
美元符号现在可以转换,但 USING 部分中的变量被 _seq_name
变量的一部分覆盖。我尝试用下划线替换序列名称中的斜杠,但没有任何改变。
我也按照here的建议通过format()
结合USING进行了尝试,但没有任何改变,出现同样的错误:
EXECUTE format('CREATE SEQUENCE %I MINVALUE $1 MAXVALUE $2 ', _seq_name)
USING _min::INT, _max::INT;
EXECUTE format('CREATE SEQUENCE %I MINVALUE ' || $1 || ' MAXVALUE ' || $2, _nazev_seq)
USING _min::INT, _max::INT;
然后我用 format()
参数完全替换了 USING 部分:
EXECUTE format('CREATE SEQUENCE %I MINVALUE %L MAXVALUE %L ', _seq_name, _min::INT, _max::INT);
现在我几乎到了我想去的地方,错误是不同的:
ERROR: syntax error at or near "'101'"
LINE 1: CREATE SEQUENCE "hu01/1/0_seq" MINVALUE '101' MAXVALUE '500'...
我在“how to use integer within FORMAT()”上发现了一个问题,其中一个答案建议%s
。现在可以了:
EXECUTE format('CREATE SEQUENCE %I MINVALUE %s MAXVALUE %s ', _seq_name, _min, _max);
但是,the other answer 建议在 USING 部分中包含整数,如果没有错误,我会这样做。我的“解决方案”感觉是一个肮脏的解决方法,我想把它做对,所以我的问题是:
为什么 USING 部分和美元符号转义值对我不起作用?
【问题讨论】:
这是有意的。 参数符号的另一个限制是它们只能在 SELECT、INSERT、UPDATE 和 DELETE 命令中使用。 postgresql.org/docs/current/static/… 【参考方案1】:EXECUTE 'CREATE SEQUENCE "' || _seq_name || '" MINVALUE $1 MAXVALUE $2 '
USING _min::INT, _max::INT;
这不起作用,因为参数替换将起作用only within SELECT, INSERT, UPDATE, and DELETE commands:
对参数符号的另一个限制是它们只能在 SELECT、INSERT、UPDATE 和 DELETE 命令中使用。只有这些语句有执行计划,只有这些语句应该被参数化。
EXECUTE 'CREATE SEQUENCE "' || _seq_name || '" MINVALUE ' || $1 || ' MAXVALUE ' || $2
USING _min::INT, _max::INT;
这行不通,因为在那种情况下$1
指的是函数的1st argument。
EXECUTE format('CREATE SEQUENCE %I MINVALUE %L MAXVALUE %L ', _seq_name, _min::INT, _max::INT);
这不起作用,因为CREATE SEQUENCE
语句的MINVALUE
和MAXVALUE
选项都只接受整数,而不接受文本(并且不会在ddl 中进行隐式转换)。
EXECUTE format('CREATE SEQUENCE %I MINVALUE %s MAXVALUE %s ', _seq_name, _min, _max);
只要_min
& _max
是某种类型的整数,这是完全安全的。如果不是,请在此处使用显式强制转换。
【讨论】:
以上是关于PL/pgSQL 中的 EXECUTE...USING 中忽略了 USING 部分的主要内容,如果未能解决你的问题,请参考以下文章
PL/pgSQL 中的 EXECUTE...USING 中忽略了 USING 部分