我如何在 Postgres 脚本中使用变量?
How do I use a variable in Postgres scripts?
我正在开发一个使用 Postgres 作为后端的原型。我做的 SQL 不多,所以我正在摸索。我制作了一个 .pgsql
文件 运行 和 psql
来执行设置我的数据库的许多文件中的每一个,我使用一个变量来定义将要使用的模式,以便我可以测试功能不会破坏我的 "good" 实例:
\set schema_name 'example_schema'
\echo 'The Schema name is' :schema_name
\ir sql/file1.pgsql
\ir sql/file2.pgsql
这一直运作良好。我已经定义了几个可以正确扩展 :schema_name
的函数:
CREATE OR REPLACE FUNCTION :schema_name.get_things_by_category(...
由于我无法弄清楚的原因,这在我的最新功能中不起作用:
CREATE OR REPLACE FUNCTION :schema_name.update_thing_details(_id uuid, _details text)
RETURNS text
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
UPDATE :schema_name.things
...
语法错误表明它在 UPDATE
之后按字面解释 :schema_name
而不是扩展它。我如何让它在这里使用变量值而不是文字值?我知道也许在 BEGIN..END
中是一个不同的上下文,但肯定有一种方法可以在所有地方编写这个模式名称的脚本?
Variable interpolation will not be performed within quoted SQL literals and identifiers. Therefore, a construction such as ':foo'
doesn't work to produce a quoted literal from a variable's value (and it would be unsafe if it did work, since it wouldn't correctly handle quotes embedded in the value).
现在函数体是一个“dollar-quoted%rdquo;字符串字面量 ($BODY$...$BODY$
),因此变量不会被替换。
我想不出用 psql
变量来做到这一点的方法。
我可以想到三种方法,因为 psql
不能直接这样做。
Shell 脚本
使用 bash 脚本执行变量替换并将结果通过管道传输到 psql
,例如。
#!/bin/bash
$schemaName =
$contents = `cat script.sql | sed -e 's/@SCHEMA_NAME@/$schemaName'`
echo $contents | psql
如果您有很多 .sql 脚本,这可能会是很多样板。
暂存架构
使用类似 staging
的硬编码模式保持您现在的方法,然后使用 bash 脚本将 staging
重命名为您想要的任何实际模式成为。
自定义搜索路径
您的入口点可以是 bash 中的内联脚本,该脚本通过管道传输到 psql,预先更新默认连接模式,然后使用 \ir 包含所有您的 .sql
文件,这些文件应该 而不是 指定架构。
#!/bin/bash
$schemaName =
psql <<SCRIPT
SET search_path TO $schemaName;
\ir sql/file1.pgsql
\ir sql/file2.pgsql
SCRIPT
一些细节:How to select a schema in postgres when using psql?
就我个人而言,我倾向于后一种方法,因为它似乎最简单且最具可扩展性。
我正在开发一个使用 Postgres 作为后端的原型。我做的 SQL 不多,所以我正在摸索。我制作了一个 .pgsql
文件 运行 和 psql
来执行设置我的数据库的许多文件中的每一个,我使用一个变量来定义将要使用的模式,以便我可以测试功能不会破坏我的 "good" 实例:
\set schema_name 'example_schema'
\echo 'The Schema name is' :schema_name
\ir sql/file1.pgsql
\ir sql/file2.pgsql
这一直运作良好。我已经定义了几个可以正确扩展 :schema_name
的函数:
CREATE OR REPLACE FUNCTION :schema_name.get_things_by_category(...
由于我无法弄清楚的原因,这在我的最新功能中不起作用:
CREATE OR REPLACE FUNCTION :schema_name.update_thing_details(_id uuid, _details text)
RETURNS text
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
UPDATE :schema_name.things
...
语法错误表明它在 UPDATE
之后按字面解释 :schema_name
而不是扩展它。我如何让它在这里使用变量值而不是文字值?我知道也许在 BEGIN..END
中是一个不同的上下文,但肯定有一种方法可以在所有地方编写这个模式名称的脚本?
Variable interpolation will not be performed within quoted SQL literals and identifiers. Therefore, a construction such as
':foo'
doesn't work to produce a quoted literal from a variable's value (and it would be unsafe if it did work, since it wouldn't correctly handle quotes embedded in the value).
现在函数体是一个“dollar-quoted%rdquo;字符串字面量 ($BODY$...$BODY$
),因此变量不会被替换。
我想不出用 psql
变量来做到这一点的方法。
我可以想到三种方法,因为 psql
不能直接这样做。
Shell 脚本
使用 bash 脚本执行变量替换并将结果通过管道传输到 psql
,例如。
#!/bin/bash
$schemaName =
$contents = `cat script.sql | sed -e 's/@SCHEMA_NAME@/$schemaName'`
echo $contents | psql
如果您有很多 .sql 脚本,这可能会是很多样板。
暂存架构
使用类似 staging
的硬编码模式保持您现在的方法,然后使用 bash 脚本将 staging
重命名为您想要的任何实际模式成为。
自定义搜索路径
您的入口点可以是 bash 中的内联脚本,该脚本通过管道传输到 psql,预先更新默认连接模式,然后使用 \ir 包含所有您的 .sql
文件,这些文件应该 而不是 指定架构。
#!/bin/bash
$schemaName =
psql <<SCRIPT
SET search_path TO $schemaName;
\ir sql/file1.pgsql
\ir sql/file2.pgsql
SCRIPT
一些细节:How to select a schema in postgres when using psql?
就我个人而言,我倾向于后一种方法,因为它似乎最简单且最具可扩展性。