web-dev-qa-db-ja.com

PostgreSQLの基本的なトランザクションDDLスクリプト

PostgreSQLの初心者は、Postgres 9.3でデータベースとそのスキーマをアトミックに作成するトランザクションDDLスクリプトをまとめようとしています。トランザクションで、いくつかのテーブルを作成します。エラーが発生した場合は、全体をロールバックします。それ以外の場合はコミットします。構文を正しく理解するのに苦労しており、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またはその近くで構文エラーが発生します。 OK、そのためEXCEPTIONはPL/pgSQLである必要があり、これはすべてPL/pgSQL宣言で行う必要があります。もう一度やってみましょう:

http://www.postgresql.org/docs/9.3/static/plpgsql-structure.html の文法によれば、これは次のようになります。

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

これに名前を付ける必要はありません。これは1回限りのプロビジョニングスクリプトであり、再び使用する関数を宣言していません。ですから、宣言をスキップして、statementsを以前のように展開します。

BEGIN

    BEGIN;

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

    EXCEPTION WHEN OTHERS THEN ROLLBACK; 

    COMMIT;

END;

これは、BEGINEXCEPTIONに構文エラーが発生し、さらに悪い方法で爆発します。その後、残りのスクリプトを実行し続け、トランザクションに参加していないことを報告します。

私がここに持っている誤解は何ですか?

5
user574835783

エラーが発生した場合は、全体をロールバックします。

思っているよりも簡単です。トランザクションの例外(何らかの方法でトラップされない)は、トランザクション全体に対してROLLBACKをトリガーします自動的にanything追加する必要はありません。

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

トランザクションを開始、コミット、またはロールバックすることはできませんinsideplpgsql すべて]、plpgsqlブロックのためis always外部トランザクションのコンテキストで自動的に実行されます。

トランザクション管理用のSQLコマンドplpgsqlコードブロック の要素と混同しないでください。 BEGINは両方でキーワードとして使用されますが、それだけが共通しています。 SQLコマンドはplpgsqlコード内では使用できず、plpgsqlコードブロックの外側にはplpgsqlコマンドがないため、これがあいまいになることはありません。

Plpgsqlブロックの EXCEPTION句はエラーのトラップにのみ使用されます で、ROLLBACKの前または代わりに何かを行います。もちろん、それはdoROLLBACKが実行しないものndo- メッセージを上げる にのみ意味がありますロールバックされることはありません。
デモンストレーションされたコードにはこれは必要ありません。

4