让我们考虑以下示例(从 psql 脚本开始):
\c :db_to_run_on
TRUNCATE the_most_important_table;
-- tried to avoid similarities to anything that exists out there
Run Code Online (Sandbox Code Playgroud)
现在,如果它通过命令运行
psql [connection details] -v db_to_run_on=\'dev_database\'
Run Code Online (Sandbox Code Playgroud)
然后它就会运行并且用户很高兴。但是,如果(她)他决定指定-v db_to_run_on=production_database怎么办?(让我们假设这可能发生,就像人们rm -rf / # don't try this at home!!!偶尔运行一样。)希望该表有一个新的备份......
所以问题出现了:如何检查传递给脚本的变量并根据它们的值停止进一步处理?
dez*_*zso 16
有一个选项可以在psql出错时停止执行命令,这是ON_ERROR_STOP. 如果我们能以某种方式引发错误,这将达到我们想要的效果。
问题是我们必须测试变量并以某种方式产生错误。由于不能在psql(因为没有)*中使用控制结构,我唯一的想法是使用 SQL 进行测试。好吧,有条件地产生错误pl/pgsql是非常擅长的,所以我写了一个会产生错误的函数。我现在可以从一个简单的CASE结构中调用这个函数。一个简单的例子:
-- let's assume for clarity that there is no function with this name in the database
CREATE OR REPLACE FUNCTION error_generator()
RETURNS boolean AS
$body$
BEGIN
RAISE 'Meaningful error message here';
RETURN FALSE; -- just for aesthetical purposes
END;
$body$
LANGUAGE plpgsql;
\set ON_ERROR_STOP on
BEGIN;
-- test for the variable value
-- notice that if :var is not set, it fails as well (with a syntax error)
SELECT CASE WHEN 1 = :var THEN error_generator() ELSE TRUE END;
INSERT INTO test_table (integer_value, text_value)
VALUES (:var, 'something');
COMMIT;
Run Code Online (Sandbox Code Playgroud)
*:您可以在 shell 之后\!和条件下使用任何 shell 命令,但是由于\!打开了一个新的 shell,因此在那里执行任何操作都不会对当前的 psql 脚本产生任何影响。
PostgreSQL 10 为 psql 带来了条件。这不再是问题。
\if :db_to_run_on = 'dev_database'
TRUNCATE the_most_important_table;
\endif
Run Code Online (Sandbox Code Playgroud)
我想你也可以使用DO..
\if :db_to_run_on != 'dev_database'
do $$
BEGIN
RAISE 'Meaningful error message here';
END;
$$ LANGUAGE plpgsql;
\endif
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15609 次 |
| 最近记录: |