62

この情報は簡単に見つけられるはずですが、運がありませんでした。

BEGIN - ENDPL/SQL にブロックがある場合、それはアトミック トランザクションとして動作しENDますか? ブロックにヒットするとコミットが試行され、問題が発生した場合は変更がロールバックされますか?

そうでない場合、BEGIN - END ブロック内のコードがアトミック トランザクションのように動作するようにするにはどうすればよいですか?また、ブロックは「デフォルトで」どのように動作しますか?

編集:ストアドプロシージャから実行しており、暗黙のブロックを使用していると思います。

4

4 に答える 4

75

まず、BEGIN..END単なる構文要素であり、トランザクションとは何の関係もありません。

次に、Oracle では、個々の DML ステートメントはすべてアトミックです (つまり、完全に成功するか、最初の失敗時に中間の変更をロールバックします) (EXCEPTIONS INTO オプションを使用しない限り、ここでは説明しません)。

ステートメントのグループを単一のアトミック トランザクションとして扱いたい場合は、次のようにします。

BEGIN
  SAVEPOINT start_tran;
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK TO start_tran;
    RAISE;
END;

そうすれば、例外が発生すると、このブロック内のステートメントはロールバックされますが、このブロックの前に実行されたステートメントはロールバックされません。

COMMIT を含めていないことに注意してください。通常は、呼び出しプロセスがコミットを発行することを好みます。


例外ハンドラのない BEGIN..END ブロックがこれを自動的に処理することは事実です。

BEGIN
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
END;

例外が発生すると、すべての挿入と更新がロールバックされます。ただし、例外ハンドラーを追加するとすぐにロールバックされません。したがって、私はセーブポイントを使用した明示的な方法を好みます。

于 2012-08-16T02:00:22.530 に答える
8

BEGIN-ENDブロックは PL/SQL の構築ブロックであり、各 PL/SQL ユニットは少なくとも 1 つのそのようなブロック内に含まれます。ネスティングBEGIN- ENDPL/SQL ブロック内のブロックは、通常、特定の例外をトラップしてその特別な例外を処理し、関連のない例外を発生させるために行われます。ただし、PL/SQL では、ユーザー (クライアント) は常にトランザクションのコミットまたはロールバックを発行する必要があります。

PL/SQL を含むトランザクション内にアトミック トランザクションが必要な場合PRAGMA AUTONOMOUS_TRANSACTIONは、宣言ブロックで a を宣言する必要があります。これにより、そのブロック内のすべての DML を、含まれているトランザクションとは無関係にコミットまたはロールバックできるようになります。

ただし、ネストされたブロックに対してこのプラグマを宣言することはできません。これは次の場合にのみ宣言できます。

  • 最上位の(ネストされていない)無名PL/SQLブロック
  • リスト項目
  • ローカル、スタンドアロン、およびパッケージ化された関数とプロシージャ
  • SQL オブジェクト型のメソッド
  • データベース トリガー

参考:オラクル

于 2012-08-15T18:38:25.063 に答える
1

これが匿名のPL/SQLブロックなのか、宣言的なブロックなのかについては言及していません。パッケージ、プロシージャ、または関数。ただし、PL/SQL では、トランザクションをデータベースに保存するために COMMIT を明示的に行う必要があります。COMMIT は、実際には、保存されていないすべてのトランザクションを現在のユーザーのセッションからデータベースに保存します。

エラーが発生した場合、トランザクションは暗黙的に ROLLBACK を実行します。

これは PL/SQL のデフォルトの動作です。

于 2012-08-15T08:29:26.647 に答える