Postgresql

如何有條件地停止 psql 腳本(基於變數值)?

  • January 17, 2022

讓我們考慮以下範例(從 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 腳本沒有任何影響。

引用自:https://dba.stackexchange.com/questions/24518