G-3320: Try to move transactions within a non-cursor loop into procedures.
Major
Maintainability, Reusability, Testability
Reason
Commit inside a non-cursor loop (other loop types than loops over cursors - see also G-3310) is either a self-contained atomic transaction, or it is a chunk (with suitable restartability handling) of very large data manipulations. In either case encapsulating the transaction in a procedure is good modularity, enabling reuse and testing of a single call.
Example (bad)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | begin
<<create_headers>>
for l_counter in 1..5
loop
insert into headers (id,text) values (l_counter,'Number ' || l_counter);
insert into lines (header_id,line_no,text)
select l_counter,rownum,'Line ' || rownum
from dual
connect by level <= 3;
commit;
end loop create_headers;
end;
/
|
Example (good)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | declare
procedure create_rows(
in_header_id in headers.id%type
) is
begin
insert into headers (id,text) values (in_header_id,'Number ' || in_header_id);
insert into lines (header_id,line_no,text)
select in_header_id,rownum,'Line ' || rownum
from dual
connect by level <= 3;
commit;
end;
begin
<<create_headers>>
for l_counter in 1..5
loop
create_rows(l_counter);
end loop create_headers;
end;
/
|