我如何在 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 中是一个不同的上下文,但肯定有一种方法可以在所有地方编写这个模式名称的脚本?

The documentation 说:

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?

就我个人而言,我倾向于后一种方法,因为它似乎最简单且最具可扩展性。