他のバージョンの文書 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

41.8. トランザクション制御 #

CALLコマンドで呼び出されたプロシージャ、また同様に無名コードブロック(DOコマンド)では、COMMITおよびROLLBACKコマンドを使ってトランザクションを終えることができます。 トランザクションをこれらコマンドで終了した後、新たなトランザクションが自動的に開始されます。そのため、別途のSTART TRANSACTIONはありません。 (PL/pgSQLではBEGINENDは別の意味を持つことに注意してください。)

以下に例を示します。

CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
    FOR i IN 0..9 LOOP
        INSERT INTO test1 (a) VALUES (i);
        IF i % 2 = 0 THEN
            COMMIT;
        ELSE
            ROLLBACK;
        END IF;
    END LOOP;
END;
$$;

CALL transaction_test1();

新しいトランザクションは、トランザクション分離レベル等のデフォルトのトランザクションの特性で開始します。 トランザクションがループ内でコミットされた場合、新しいトランザクションは前のトランザクションと同じ特性で自動的に開始するのが好ましいかもしれません。 コマンドCOMMIT AND CHAINROLLBACK AND CHAINはそのように動作します。

トランザクション制御は、トップレベル、または、他の干渉するコマンドを伴わない入れ子のCALLまたはDO呼び出しからの、CALLまたはDOによる呼び出しのみで可能です。 例えば、呼び出しスタックがCALL proc1()CALL proc2()CALL proc3()である場合、二番目と三番目のプロシージャはトランザクション制御を実行できます。 しかし、呼び出しスタックがCALL proc1()SELECT func2()CALL proc3()である場合、間のSELECTのため、最後のプロシージャはトランザクション制御を実行できません。

PL/pgSQLはセーブポイント(SAVEPOINT/ROLLBACK TO SAVEPOINT/RELEASE SAVEPOINTコマンド)をサポートしません。 セーブポイントの典型的な使用パターンは、例外ハンドラを持つブロックに置き換えることができます(41.6.8を参照してください)。 内部では、例外ハンドラを持つブロックがサブトランザクションを形成します。これは、そのようなブロック内ではトランザクションを終了できないことを意味します。

カーソルループには特別な考慮事項が当てはまります。 以下の例をよく確認してください。

CREATE PROCEDURE transaction_test2()
LANGUAGE plpgsql
AS $$
DECLARE
    r RECORD;
BEGIN
    FOR r IN SELECT * FROM test2 ORDER BY x LOOP
        INSERT INTO test1 (a) VALUES (r.x);
        COMMIT;
    END LOOP;
END;
$$;

CALL transaction_test2();

通常、カーソルはトランザクションのコミット時に自動的に閉じられます。 しかしながら、このようにループの一部として作られたカーソルは、最初のCOMMITまたはROLLBACKから自動的に保持可能カーソルに変換されます。 このことは、カーソルが行ごとではなく、最初にCOMMITROLLBACKされた時点で全体として評価されることを意味します。 従来通りカーソルはループ後に自動で削除されるので、このことはユーザにほとんど認識されません。 しかし、カーソルの問い合わせによって取得されたテーブルまたは行のロックは、最初のCOMMITまたはROLLBACKの後にはもはや保持されないことに留意しなければなりません。

トランザクションコマンドは、読み込み専用でないコマンド(例えばUPDATE ... RETURNING)で駆動されるカーソルループ内では許可されません。