私のOracleストアドプロシージャには、次のような複数の挿入および更新ステートメントがあります。
create or replace PROCEDURE SPTest
AS
BEGIN
insert into emptest(empid,empname,deptno)
(1,'ravi',10);
insert into test1(id,name,sal)
(1,'raju',4444);
update emptest set empname='hari' where empid=1;
END;
ステートメントでエラーが発生した場合、すべての挿入ステートメントと更新ステートメントをロールバックしたいと思います。
このストアドプロシージャにコミットとロールバックを実装するにはどうすればよいですか?
これは、セーブポイントを使用して行うことができます。
_create or replace PROCEDURE SPTest
AS
BEGIN
-- We create a savepoint here.
SAVEPOINT sp_sptest;
insert into emptest(empid,empname,deptno)
(1,'ravi',10);
insert into test1(id,name,sal)
(1,'raju',4444);
update emptest set empname='hari' where empid=1;
-- If any exception occurs
EXCEPTION
WHEN OTHERS THEN
-- We roll back to the savepoint.
ROLLBACK TO sp_sptest;
-- And of course we raise again,
-- since we don't want to hide the error.
-- Not raising here is an error!
RAISE;
END;
_
通常、コミットは呼び出し元に任されます。この構成は、すべての挿入と更新が行われるか、どれも行われないことを保証するだけです。
最も外側のレベルでは、Oracleはそれ自体でロールバックを行います。つまり、SQL +コマンドラインでEXEC sptest();
を実行すると、自動的に展開されます
_DECLARE
BEGIN
sptest();
EXCEPTION
ROLLBACK;
END;
_
ただし、呼び出し元のプロシージャに例外処理がある場合、例外はその外部レベルに到達しない可能性があるため、これは発生しません。そのため、挿入が完了し、更新によって例外がスローされ、呼び出し元によってキャッチおよび処理される可能性があるため、更新は失敗しますが、挿入は成功します。
ストアドプロシージャでプロシージャの先頭にロールバックすることで、すべてが成功するか、どれも成功しないことを保証します。
--Rollback on Exception else Commit;
--SET TRANSACTION READ WRITE;
BEGIN
SAVEPOINT ABC;
update table_A set column1 ='Y' where id = 69;
update table_A set column2 ='S' where id = 70;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO ABC;
COMMIT;
END;
--createdon is of datetime type and has an exception. So rollback will happen.