web-dev-qa-db-ja.com

関数/手順でのDML操作の後にコミットは必要ですか?

関数/プロシージャの挿入/削除/更新後にコミットを書き込む必要があるかどうか知りたいですか?

例:

create or replace function test_fun
return number is
begin
   delete from a;
   return 0;
end;

または手順

create or replace procedure aud_clear_pro
as
begin
   delete from a;
end;

削除後にコミットする必要がありますか?

次の状況を理解できません:

  1. SQLウィンドウから関数/プロシージャを呼び出すと、コミットが必要になります

    だが

  2. Dbms_schedulerを使用して関数/プロシージャをスケジュールし、ジョブを実行すると、deleteステートメントが自動的にコミットされます。

    どうして?

20
kupa

一般に、手順はコミットしないでください。これらの種類のトランザクション制御の決定は、論理トランザクションが実際にいつ完了したかを知る上位レベルのコードに任せる必要があります。ストアドプロシージャ内でコミットする場合、プロシージャがより大きなトランザクションの一部になるようにする変更を必要とする呼び出し元は、プロシージャを直接呼び出すことはできないため、再利用性が制限されます。

プロシージャをインタラクティブに呼び出す場合、Oracleは、プロシージャコールを論理トランザクションにするのか、複数のプロシージャコールを含むより大きなトランザクションを構成するのかわからないため、トランザクションを明示的にコミットまたはロールバックする必要があります。 dbms_schedulerを使用する場合、dbms_schedulerは、ジョブが論理トランザクションであると見なし、ジョブの最後に成功したと見なしてコミットします(dbms_jobも同じことを行います)。

関数はそもそもデータを操作すべきではありません。データを操作する関数は、SQLステートメントから呼び出すことはできません(関数自体が自律型トランザクションを使用するように宣言されているコーナーケースを除き、ほとんど適切ではありません)。関数とプロシージャの両方を持つことの要点は、関数をSQLステートメントに埋め込むことができ、ユーザーがデータを変更しないため、より自由にユーザーに付与できることです。

24
Justin Cave

あなたの質問に答えるために;どうして?

投稿は2歳なので、おそらくもうご存じでしょう。ただし、念のために回答します。

#1がコミットを必要とし、#2がコミットを必要としない理由は、Oracleのデフォルトのデータベース設定では、セッションの終了時にトランザクションをコミットするためです。 sqlplusでコードを手動で実行した場合、トランザクションはすぐにはコミットされません。明示的なコミットを発行する場合OR sqlpusからログオフすると、トランザクションがコミットされます。

#2で自動コミットを取得するのは、スクリプトを実行するセッションを作成するためです。完了すると自動的にログオフし、自動コミットが行われます。

4