Postgresql
如何有條件地停止 psql 腳本(基於變數值)?
讓我們考慮以下範例(從 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!!!
。)希望該表有一個新的備份……那麼問題來了:如何檢查傳遞給腳本的變數並根據它們的值停止進一步處理?
PostgreSQL 10
PostgreSQL 10 為 psql 帶來了條件。這不再是一個問題。
\if :db_to_run_on = 'dev_database' TRUNCATE the_most_important_table; \endif
我想你也可以使用
DO
..\if :db_to_run_on != 'dev_database' do $$ BEGIN RAISE 'Meaningful error message here'; END; $$ LANGUAGE plpgsql; \endif
有一個選項可以在
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;
*:您可以在 shell 之後
\!
和條件句之後使用任何 shell 命令,但是由於\!
打開了一個新的 shell,因此執行那裡的任何內容對目前的 psql 腳本沒有任何影響。