То, что вы запрашиваете, является более или менее стандартным поведением:
create table test1 (id integer not null);
create table test2 (id integer not null);
create table test3 (id integer not null);
create or replace procedure myProcedure
( p1 test1.id%type
, p2 test2.id%type
, p3 test3.id%type )
as
begin
insert into test1 (id) values (p1);
insert into test2 (id) values (p2);
insert into test3 (id) values (p3);
end myProcedure;
/
call myProcedure(1, 2, 3);
-- completes successfully
call myProcedure(1, 2, null);
-- fails with:
-- ERROR at line 1:
-- ORA-01400: cannot insert NULL into ("WILLIAM"."TEST3"."ID")
-- ORA-06512: at "WILLIAM.MYPROCEDURE", line 9
select 'test1' as table_name, test1.id from test1 union all
select 'test2', test2.id from test2 union all
select 'test3', test3.id from test3
order by 1;
TABLE ID
----- ----------
test1 1
test2 2
test3 3
3 rows selected.
Итак, у меня есть три строки из вызова, который завершился успешно, и ничего из вызова, который не удался, все без явной фиксации илиоткат.
Вы можете добавить commit
в конец процедуры, если вы действительно хотите, чтобы она была зафиксирована (не всегда хорошая идея, но требования варьируются).
Однако , поведение по умолчанию «откат к неявной точке сохранения» имеет место, только если исключение распространяется до самого вызывающего, например, если я пытаюсь обработать его с помощью:
begin
delete test1;
delete test2;
delete test3;
myProcedure(1, 2, null);
exception
when others then
dbms_output.put_line(sqlerrm);
dbms_output.put_line(dbms_utility.format_error_backtrace);
end;
ORA-01400: cannot insert NULL into ("WILLIAM"."TEST3"."ID")
ORA-06512: at "WILLIAM.MYPROCEDURE", line 9
ORA-06512: at line 6
PL/SQL procedure successfully completed.
Сейчас, поскольку блок завершен успешно, у меня есть значения из прогона, который не прошел частично:
select 'test1' as table_name, test1.id from test1 union all
select 'test2', test2.id from test2 union all
select 'test3', test3.id from test3
order by 1;
TABLE ID
----- ----------
test1 1
test2 2
2 rows selected.
В любом случае, чтобы обработать все это явно, вы можете захотеть что-то вроде этого:
create or replace procedure myProcedure
( p1 test1.id%type
, p2 test2.id%type
, p3 test3.id%type )
as
begin
savepoint start_of_processing;
insert into test1 (id) values (p1);
insert into test2 (id) values (p2);
insert into test3 (id) values (p3);
commit;
exception
when others then
rollback to start_of_processing;
-- Log using whatever logging package you have:
logger.message('Something appears to have gone disastrously amiss');
raise;
end myProcedure;
Имейте в виду, однако, что акт наблюдения исключения меняет его безвозвратно .Насколько я знаю, это верно для всех языков программирования.