M0l*_*les 4 postgresql psql sequence dynamic-sql ddl
我已经用 Postgres 玩了一个星期左右,我正在看看是否可以使用表达式设置序列的最小值/最大值。具体目标是为服务器之间的不相交范围自动创建脚本,以避免多主设置中的密钥冲突。
例如,使用 psql:
CREATE SEQUENCE key_seq MINVALUE (:servernum * :stride)
MAXVALUE ((:servernum + 1) * :stride - 1);
Run Code Online (Sandbox Code Playgroud)
这给了我一个语法错误。变量是逐字内插的,不进行计算。
另一种方法是根据表达式的输出设置变量:
\set minvalue (:servernum * :stride)
Run Code Online (Sandbox Code Playgroud)
但该\set
语句不计算表达式。
您需要\set
(不是\pset
!)设置psql变量。与 Unix shell 中的赋值不同,psql 赋值不能进行算术运算。您可以使用 psql 命令\!
来执行 shell 命令,但我会建议两种不同的方法:
\gset
将当前查询输入缓冲区发送到服务器并将查询的输出存储到 psql 变量中
然后您可以将计算出的数字插入为文本,一切正常。
psql 代码:
test=# \set servernum 5
test=# \set stride 300
test=# SELECT :servernum * :stride AS minvalue, (:servernum + 1) * :stride - 1 AS maxvalue \gset
test=# CREATE SEQUENCE key_seq MINVALUE :minvalue MAXVALUE :maxvalue;
CREATE SEQUENCE
Run Code Online (Sandbox Code Playgroud)
一个很好的博客解释\gset
:
我计算和设置:minvalue
并:maxvalue
在一个单一 SELECT
的优化性能。尽管如此,这种方法的缺点是您需要额外往返 Postgres 服务器。
不会在引用的 SQL 文字和标识符内执行变量插值。
这会使字符串连接复杂化。我建议创建一个函数并format()
用于干净的代码。如果它仅用于当前会话,您可以通过模式限定使其成为临时函数,pg_temp.
因此该函数仅对您的当前会话可见,并在会话结束时删除。临时功能是一个未记录的功能 - 即使是由 Tom Lane 建议的。细节:
所以:
test=# CREATE FUNCTION pg_temp.f_my_seq(_seq text, _servernum int, _stride int)
RETURNS void AS
$func$
BEGIN
EXECUTE format('CREATE SEQUENCE %I MINVALUE %s MAXVALUE %s'
, _seq, _servernum * _stride, (_servernum + 1) * _stride - 1);
END
$func$ LANGUAGE plpgsql;
test=# \set servernum 5
test=# \set stride 300
test=# SELECT pg_temp.f_my_seq('key_seq', :servernum, :stride);
Run Code Online (Sandbox Code Playgroud)
我们需要动态 SQL 与EXECUTE
. 关于变量替换的手册:
变量替换目前仅适用于
SELECT
、INSERT
、UPDATE
和DELETE
命令,因为主 SQL 引擎仅允许在这些命令中使用查询参数。要在其他语句类型(通常称为实用程序语句)中使用非常量名称或值,您必须将实用程序语句构造为字符串和EXECUTE
它。
SO的相关答案:
归档时间: |
|
查看次数: |
2169 次 |
最近记录: |