バルクインサートスクリプト

※コピーすると改行が抜ける場合はソースをダブルクリックして強調表示を外してからコピーしてください

--CREATE TABLE SCOTT.EMP_COPY AS SELECT * FROM SCOTT.EMP WHERE ROWNUM < 0;
--ALTER TABLE SCOTT.EMP_COPY ADD CONSTRAINTS PK_EMP_COPY PRIMARY KEY(EMPNO);

--基本
set serveroutput on
DECLARE
    BULK_NUM CONSTANT PLS_INTEGER := 5; --バルクサイズ
    --CURSOR
    CURSOR CUR_EMP IS
    SELECT * FROM SCOTT.EMP ORDER BY EMPNO;
    --TYPE
    TYPE TYPE_EMP IS TABLE OF CUR_EMP%ROWTYPE INDEX BY BINARY_INTEGER;
    REC_EMP TYPE_EMP;
BEGIN
    OPEN CUR_EMP;
    LOOP
        FETCH CUR_EMP BULK COLLECT INTO REC_EMP LIMIT BULK_NUM;
        EXIT WHEN REC_EMP.COUNT = 0;
        DBMS_OUTPUT.PUT_LINE('フェッチ数:' || REC_EMP.COUNT);
        --バルクインサート
        FORALL i in 1..REC_EMP.COUNT
        INSERT INTO SCOTT.EMP_COPY VALUES REC_EMP(i);
        COMMIT;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('合計フェッチ数:' || CUR_EMP%ROWCOUNT);
    CLOSE CUR_EMP;
end;
/

--エラー発生時、即バルク処理を中断する
set serveroutput on
DECLARE
    BULK_NUM CONSTANT PLS_INTEGER := 5; --バルクサイズ
    --CURSOR
    CURSOR CUR_EMP IS
    SELECT * FROM SCOTT.EMP ORDER BY EMPNO;
    --TYPE
    TYPE TYPE_EMP IS TABLE OF CUR_EMP%ROWTYPE INDEX BY BINARY_INTEGER;
    REC_EMP TYPE_EMP;
BEGIN
    OPEN CUR_EMP;
    LOOP
        FETCH CUR_EMP BULK COLLECT INTO REC_EMP LIMIT BULK_NUM;
        EXIT WHEN REC_EMP.COUNT = 0;
        DBMS_OUTPUT.PUT_LINE('フェッチ数:' || REC_EMP.COUNT);
        BEGIN
            --バルクインサート
            FORALL i in 1..REC_EMP.COUNT
            INSERT INTO SCOTT.EMP_COPY VALUES REC_EMP(i);
            COMMIT;
        EXCEPTION
            WHEN DUP_VAL_ON_INDEX THEN  --ORA-00001が発生した場合
                DBMS_OUTPUT.PUT_LINE('エラー発生行 ' || SQL%BULK_EXCEPTIONS(1).ERROR_INDEX);
                DBMS_OUTPUT.PUT_LINE('エラーメッセージ ' ||
                SQLERRM(-SQL%BULK_EXCEPTIONS(1).ERROR_CODE));
                ROLLBACK;
                RAISE;
        END;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('合計フェッチ数:' || CUR_EMP%ROWCOUNT);
    CLOSE CUR_EMP;
end;
/

--エラー発生時もバルク処理は継続する
set serveroutput on
DECLARE
    BULK_NUM CONSTANT PLS_INTEGER := 5; --バルクサイズ
    --CURSOR
    CURSOR CUR_EMP IS
    SELECT * FROM SCOTT.EMP ORDER BY EMPNO;
    --TYPE
    TYPE TYPE_EMP IS TABLE OF CUR_EMP%ROWTYPE INDEX BY BINARY_INTEGER;
    REC_EMP TYPE_EMP;

    --エラー発生回数
    V_ERROR_COUNT PLS_INTEGER := 0;
    --ORA-24381用の例外ハンドラ
    EX_ORA24381 EXCEPTION;
    PRAGMA EXCEPTION_INIT(EX_ORA24381, -24381);
BEGIN
    OPEN CUR_EMP;
    LOOP
        FETCH CUR_EMP BULK COLLECT INTO REC_EMP LIMIT BULK_NUM;
        EXIT WHEN REC_EMP.COUNT = 0;
        DBMS_OUTPUT.PUT_LINE('フェッチ数:' || REC_EMP.COUNT);
        BEGIN
            V_ERROR_COUNT := 0;
            --バルクインサート
            FORALL i in 1..REC_EMP.COUNT SAVE EXCEPTIONS --エラー時も継続
            INSERT INTO SCOTT.EMP_COPY VALUES REC_EMP(i);
            COMMIT;
        EXCEPTION
            WHEN EX_ORA24381 THEN
            V_ERROR_COUNT := V_ERROR_COUNT + SQL%BULK_EXCEPTIONS.COUNT;
            DBMS_OUTPUT.PUT_LINE('エラー件数:' || V_ERROR_COUNT);
            FOR i IN 1..V_ERROR_COUNT LOOP
                DBMS_OUTPUT.PUT_LINE('#' || i || ' エラー発生行 '||
                  SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
                DBMS_OUTPUT.PUT_LINE('エラーメッセージ ' ||
                  SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
            END LOOP;
        END;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('合計フェッチ数:' || CUR_EMP%ROWCOUNT);
    CLOSE CUR_EMP;
end;
/


マニュアル

Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス(10.2)
PL/SQL ユーザーズ・ガイドおよびリファレンス(10.2)
★ORACLE案件承ります