Postgresql

PostgreSQL 中的基本事務 DDL 腳本

  • November 14, 2021

PostgreSQL 新手在這裡嘗試將事務 DDL 腳本放在一起,以在 Postgres 9.3 中原子地創建數據庫及其模式:在事務中,創建幾個表;如果有任何錯誤,請將整個內容回滾;否則送出。我很難獲得正確的語法,我懷疑我的問題可能源於將 SQL DDL 與 PL/pgSQL 混為一談和/或沒有理解事務語義。

長話短說,執行此類操作的腳本的 PL/pgSQL 樣板是什麼?

我的嘗試是這樣schema.sql的:

BEGIN;

CREATE TABLE IF NOT EXISTS blah ( ... ); -- much DDL

EXCEPTION WHEN OTHERS THEN ROLLBACK; -- this, I gather, is PL/pgSQL

COMMIT;

\i schema.sql在 psql 提示符處或附近產生語法錯誤EXCEPTION。好的,所以EXCEPTION必須是 PL/pgSQL,所有這些都需要放在 PL/pgSQL 聲明中。讓我們再試一次:

根據http://www.postgresql.org/docs/9.3/static/plpgsql-structure.html的語法,這看起來像:

[ <<label>> ]
[ DECLARE
   declarations ]
BEGIN
   statements
END [ label ];

我不需要命名它,它是一次性配置腳本,而不是聲明我將再次使用的函式。所以跳過聲明並擴展statements到我之前的內容:

BEGIN

   BEGIN;

   CREATE TABLE IF NOT EXISTS blah ( ... ); -- much DDL

   EXCEPTION WHEN OTHERS THEN ROLLBACK; 

   COMMIT;

END;

這以更糟糕的方式爆發,出現語法錯誤BEGIN, EXCEPTION,然後它繼續執行腳本的其餘部分,抱怨不在事務中。

我這裡有什麼誤解?

如果有任何錯誤,請將整個內容回滾;

它比你想像的要簡單。事務中的任何異常(未以某種方式被擷取)都會自動ROLLBACK觸發整個事務。你不必做任何額外的事情。

BEGIN;
CREATE TABLE IF NOT EXISTS blah ( ... );
-- much more DDL
COMMIT;

您根本無法在plpgsql啟動、送出或回滾事務,因為 plpgsql 塊總是在外部事務的上下文中自動執行。

不要將用於事務管理的 SQL 命令與plpgsql 程式碼塊的元素混淆。BEGIN在兩者中都用作關鍵字,這是唯一的共同點。這絕不是模棱兩可的,因為 SQL 命令在 plpgsql 程式碼中不可用,並且在 plpgsql 程式碼塊之外沒有 plpgsql 命令。

plpgsql 塊中的EXCEPTION子句僅用於擷取錯誤並在ROLLBACK. 當然,只有一些ROLLBACK不會撤消的事情才有意義——比如提出一個永遠不會回滾的消息。

您的展示程式碼不需要任何這些。

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