PL/SQL

PLSQL バルク処理 LEFT-JOIN

PL/SQL

こんにちは! 健史です。

バルク処理において、LEFT-JOINで表結合したデータをカーソルで定義する方法がわからず、AIに問い合わせました。

問い合わせた内容をもとにプログラムを作成しました。

スポンサーリンク

プログラム

CREATE OR REPLACE PROCEDURE PROC_BULK4 AS 
--1.バルク サイズ定義
  BULK_SIZE CONSTANT PLS_INTEGER := 2000;  -- コンスタントでなくても良い
--2.カーソル定義
  CURSOR CUR1 IS
    SELECT
        A.キー1             AS キー1,
        A.キー2             AS キー2,
        A.キー3             AS キー3,
        A.連番               AS 連番,
        A.数量               AS 数量,
        A.単価               AS 単価,
        A.団体コード         AS 団体コード,
        A.件数               AS 件数,
        B.都道府県           AS 都道府県,
        B.市区町村           AS 市区町村,
        B.都道府県カナ       AS 都道府県カナ,
        B.市区町村カナ       AS 市区町村カナ,
        B.政令指定都市区分   AS 政令指定都市区分
    FROM 売上履歴 A
    LEFT JOIN 市区町村 B
    ON A.団体コード = B.団体コード
    ORDER BY A.キー1,キー2,連番;
--3.バルク テーブル等定義
--  バルク FETCH用テーブル定義
  TYPE IN1TBL IS TABLE OF CUR1%ROWTYPE INDEX BY BINARY_INTEGER;
  IN1REC IN1TBL;
--  バルク INSERT用テーブル定義   
  TYPE OT1TBL IS TABLE OF 売上履歴集計3%ROWTYPE INDEX BY BINARY_INTEGER;
  OT1REC OT1TBL;
--  エラーハンドラ用 ORA-24381: DML配列にエラーがあります。
  vBulkErrors  PLS_INTEGER := 0;
  eBulkProcessNotComplete EXCEPTION;
  PRAGMA EXCEPTION_INIT(eBulkProcessNotComplete, -24381);
--4.ワークを定義
  入力件数 NUMBER(10);
  出力件数 NUMBER(10);
  WK_TIMESTAMP TIMESTAMP;
--5.FUNCTION定義 必要に応じて定義

--6.メイン処理
BEGIN
--6-1.初期処理
  SELECT TO_CHAR(SYSTIMESTAMP,'yyyy/mm/dd hh24:mi:ss.ff5') INTO WK_TIMESTAMP FROM DUAL;
  DBMS_OUTPUT.PUT_LINE('開始時刻:' || WK_TIMESTAMP);
  OPEN CUR1;
  EXECUTE IMMEDIATE 'TRUNCATE TABLE 売上履歴集計3';
  入力件数 := 0;
  出力件数 := 0;
  SELECT TO_CHAR(SYSTIMESTAMP,'yyyy/mm/dd hh24:mi:ss.ff5') INTO WK_TIMESTAMP FROM DUAL;
  DBMS_OUTPUT.PUT_LINE('開始時刻:' || WK_TIMESTAMP);
--6-2.順次処理
  LOOP
--  バルク FETCH,INSERT用テーブル初期クリア 
    IN1REC.DELETE;
    OT1REC.DELETE;
--  バルク処理
--  1).FETCH
    FETCH CUR1 BULK COLLECT INTO IN1REC LIMIT BULK_SIZE;
    EXIT WHEN IN1REC.COUNT = 0;
--  2).編集処理
    FOR i in 1 .. IN1REC.COUNT
    LOOP
      入力件数 := 入力件数 + 1; 
      OT1REC(i).キー1           := IN1REC(i).キー1;
      OT1REC(i).キー2           := IN1REC(i).キー2;
      OT1REC(i).キー3           := IN1REC(i).キー3;
      OT1REC(i).連番             := IN1REC(i).連番;
      OT1REC(i).数量             := IN1REC(i).数量;
      OT1REC(i).単価             := IN1REC(i).単価;
      OT1REC(i).団体コード       := IN1REC(i).団体コード;
      OT1REC(i).件数             := IN1REC(i).件数;
      OT1REC(i).都道府県         := IN1REC(i).都道府県;
      OT1REC(i).市区町村         := IN1REC(i).市区町村;
      OT1REC(i).都道府県カナ     := IN1REC(i).都道府県カナ;
      OT1REC(i).市区町村カナ     := IN1REC(i).市区町村カナ;
      OT1REC(i).政令指定都市区分 := IN1REC(i).政令指定都市区分;
      出力件数 := 出力件数 + 1; 
    END LOOP;
--  3).INSERT
    BEGIN
      FORALL i in 1..OT1REC.COUNT SAVE EXCEPTIONS  -- ← エラーが発生しても継続
        INSERT INTO 売上履歴集計3 VALUES OT1REC(i);
      COMMIT;
      EXCEPTION
      WHEN eBulkProcessNotComplete THEN
        vBulkErrors := vBulkErrors + SQL%BULK_EXCEPTIONS.COUNT;
        -- PROC_BULK_ERROR_HANDLER;
    END;    
  END LOOP;
--7.終了処理
  COMMIT;
  DBMS_OUTPUT.PUT_LINE('入力件数:' || 入力件数);
  DBMS_OUTPUT.PUT_LINE('出力件数:' || 出力件数);
  DBMS_OUTPUT.PUT_LINE('エラー数:' || vBulkErrors);
  SELECT TO_CHAR(SYSTIMESTAMP,'yyyy/mm/dd hh24:mi:ss.ff5') INTO WK_TIMESTAMP FROM DUAL;
  DBMS_OUTPUT.PUT_LINE('終了時刻:' || WK_TIMESTAMP);
  CLOSE CUR1;
END PROC_BULK4;

補足

・テーブル[市区町村]は、総務省のホームページにある「都道府県コード及び市区町村コード」のcsvを取り込みました。

・テーブル[売上履歴]の[団体コード]には、上記[市区町村]テーブルの団体コードを設定しています。
[市区町村]テーブルの先頭から設定し、最後尾に達したらまた先頭からサイクリックに設定しています。

処理時間

・2,000件  0:23

開始時刻:25-05-25 13:07:52.241000
開始時刻:25-05-25 13:07:52.741000
入力件数:1500000
出力件数:1500000
エラー数:0
終了時刻:25-05-25 13:08:15.211000

PL/SQL
スポンサーリンク
- 面白かったらシェアお願いします! -
健史をフォローする
自分で改善

コメント