FORALL 구문
참고URL
http://deviant86.tistory.com/464
위 URL의 내용을 테스트해본 것 뿐이 없으니 위 URL에서 내용 확인하는게 더 정확함
pl/sql 에서 sql엔진으로의 문맥전환을 바인딩 후 한번에 넘기는 역활을 하는 것 같음
forall cn in lower_bound .. upper_bound
sql_statment;
body 는 단일 dml 문
forall 의 cn을 참조해야함
커서
SQL%found : 마지막 DML 실행하여 적용된 ROW가 있는가
SQL%notfound : 마지막 DML 실행하여 적용된 ROW가 없는가
SQL%rowcount : 모든 SQL문 실행하여 처리된 행의 총수
sql%bulk_rowcount : 각 sql문에 의해 처리된 행의 수를 알려주는 컬렉션
롤백
- FORALL 실행 중단됨
- 암시적 세이브포인트 까지 롤백
- 이미 오류없이 처리된 FORALL 의 DML문은 롤백되지 않음
ORA-24381 : BULK DML 오류 시 EXCEPTINO 인 것 같음
INSERT, DELETE 에서는 테스트 해보는데 작동 안하는 것 같고 UPDATE에서는 작동함
URL
http://deviant86.tistory.com/464
https://docs.oracle.com/cd/B13789_01/appdev.101/b10807/13_elems021.htm
샘플소스
declare
/*
binary_integer 를 작성하지 않으면 배열 크기를 정해줘야 하는 것 같음
*/
type tbl_val is table of varchar2(30) index by binary_integer;
lt_val tbl_val;
lt_ret_val tbl_val;
le_bulk_error exception;
/*
ora-24381 : bulk dml exception
근데 왜 insert에선 안되지?
*/
pragma exception_init(le_bulk_error, -24381);
begin
/*단순 대량처리*/
for cn in 1..10 loop
lt_val(cn) := cn || '-XXXxx' || cn;
end loop;
forall cn in lt_val.first .. lt_val.last
save exceptions
insert into TEMI_LABEL_LOT(lot) values (lt_val(cn))
returning lot bulk collect into lt_ret_val
;
-- dbms_output.put_line(SQL%FOUND);
-- dbms_output.put_line('NOTFOUND : ' || SQL%NOTFOUND);
-- dbms_output.put_line('ROWCOUNT : ' || SQL%ROWCOUNT);
-- dbms_output.put_line('ROWCOUNT : ' || SQL%BULK_ROWCOUNT);
/*returning 적용
반드시 bulk collect 로 처리해야함
*/
forall cn in lt_ret_val.first .. lt_ret_val.last
update temi_label_lot set
lot = lt_ret_val(cn) || '_X'
where lot = lt_ret_val(cn)
;
/*
bulk_exceptions 처리
신기하게 insert 문은 그냥 others 를 타는데 update 문은 le_bulk_error 를 실행함
*/
forall cn in lt_ret_Val.first .. lt_ret_val.last
save exceptions
update temi_label_lot set
lot = lt_ret_val(cn) || '!'
where lot = lt_ret_val(cn) || '_X'
;
/*
동적 실행 처리
*/
forall cn in lt_ret_val.first .. lt_ret_val.last
save exceptions
execute immediate 'insert into temi_label_lot(lot, adddate) values (:new_lot, sysdate)'
using lt_ret_val(cn)
;
/*
delete bulk_exception 처리
- 이것도 발동 안함
*/
/*
forall cn in lt_ret_val.first .. lt_ret_val.last
save exceptions
execute immediate 'delete from temi_label_lot where lotx = :new_lot'
using lt_ret_val(cn)
;
*/
commit;
exception
when le_bulk_error then
dbms_output.put_line('le_bulk_error');
/*
bulk_exceptions 는 ora-24381 에서만 사용가능한 것 같음
*/
for cn in 1..SQL%bulk_exceptions.count loop
dbms_output.put_line('index : ' || sql%bulk_exceptions(cn).error_index);
dbms_output.put_line('code : ' || sql%bulk_exceptions(cn).error_code);
end loop;
when others then
dbms_output.put_line('others error');
end;