让我们考虑以下示例(从 psql 脚本开始):
\c :db_to_run_on
TRUNCATE the_most_important_table;
-- tried to avoid similarities to anything that exists out there
现在,如果它是通过命令运行的
psql [connection details] -v db_to_run_on=\'dev_database\'
然后它就会运行并且用户很高兴。但是,如果他(她)决定指定-v db_to_run_on=production_database
呢?(让我们假设这可能发生,就像人们偶尔跑步一样rm -rf / # don't try this at home!!!
。)希望该表有一个新的备份......
那么问题来了:如何检查传递给脚本的变量并根据它们的值停止进一步处理?
有一个选项可以在
psql
出错时停止执行命令,这是ON_ERROR_STOP
. 如果我们能以某种方式引发错误,这将做我们想要的。问题是我们必须测试变量并以某种方式产生错误。由于不能在
psql
(因为没有)* 中使用控制结构,我唯一的想法是使用 SQL 进行测试。好吧,有条件地产生错误pl/pgsql
是非常擅长的,所以我写了一个会产生错误的函数。我现在可以从一个简单的CASE
结构调用这个函数。一个简单的例子:*:您可以在 shell 之后
\!
和条件句之后使用任何 shell 命令,但是由于\!
打开了一个新的 shell,因此执行那里的任何内容对当前的 psql 脚本没有任何影响。PostgreSQL 10
PostgreSQL 10 为 psql 带来了条件。这不再是一个问题。
我想你也可以使用
DO
..dezso 答案的更简洁版本:
然后你可以这样称呼它:
我发现对我来说非常有效的是使用脚本语言生成一个 SQL 文件,然后我将其通过管道传输到 psql 中,如下所示:
然后,我从驱动程序脚本中调用它:
我的驱动程序脚本通常是一个 Rake 文件,但你明白了。
要退出
psql
脚本,您可以简单地使用meta 命令或在激活\quit
时生成错误。ON_ERROR_STOP
区别在于:\quit
如果使用嵌套0
脚本或\i
ON_ERROR_STOP
在打开时产生错误将退出状态3
并在嵌套脚本的情况下传播到顶级脚本。生成错误然后
RAISE
从函数或匿名代码块执行的更简单的替代方法是无效的 SQL 命令,例如:INVALID;
.要输出错误消息,您可以使用
\warn
元命令将其发送到stderr
(启动 pg13)或简单地\echo
发送到stdout
.结合
\if
(开始 pg10)我对 OP 问题的尝试将是:不幸的是,我不知道有一种方法可以抑制无效命令生成的“语法错误”输出。因此,根据您的用例组合
\warn 'You better not do this!'
and\quit
或\set ON_ERROR_STOP on
andDO $$BEGIN RAISE 'You better not do this!'; END$$ LANGUAGE plpgsql;
可能更合适。在查询脚本(我猜它与 psql 脚本有所不同)中,
\if
被认为是语法错误,但这样的代码对我有用:在 PostgreSQL 13.2 中测试。
DO
存储过程中不需要外部块。