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;
これは、BEGIN
、EXCEPTION
に構文エラーが発生し、さらに悪い方法で爆発します。その後、残りのスクリプトを実行し続け、トランザクションに参加していないことを報告します。
私がここに持っている誤解は何ですか?
エラーが発生した場合は、全体をロールバックします。
思っているよりも簡単です。トランザクションの例外(何らかの方法でトラップされない)は、トランザクション全体に対して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- メッセージを上げる にのみ意味がありますロールバックされることはありません。
デモンストレーションされたコードにはこれは必要ありません。