본문 바로가기

프로그램/oracle

[ORACLE]FORALL 구문

반응형

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;