8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PL/SQLで大量データ移行する際のメモ

Last updated at Posted at 2016-11-03

PL/SQLで大量データ移行する際のメモ

数十万~数億件のデータ移行でバルクFETCHからのINSERTが有効です。
(ダイレクトパスINSERTはまたの機会に)
BULK FETCH から INSERT / UPDATE をなるべく簡単に書く方法をすっかり忘れていたのでメモメモ。

これを忘れてしまい検索に手間取ったUPDATEの書式。「ROW=」のところがミソ。
これを使うとレコード毎UPDATEできて便利。

BULK_UPDATE

UPDATE <テーブル名>
   SET ROW = <レコード型コレクション>
 WHERE <主キー>;

INSERTもこんな感じで簡単に書ける。

BULK_INSERT
INSERT INTO <テーブル名> VALUE <レコード型コレクション>;

BULK FETCH からの INSERT / UPDATE を行うとこんな感じになる
1万件をガバッ と読んで、 変更データをコレクションにため込み 一気に UPDATE/INSERT して効率を高めます。
(便宜上、中でSELECT文を入れていますが UPDATEも例に入れたかったので^^;)

BULK_FETCH_SAMPLE
CREATE OR REPLACE PROCEDURE BULK_FETCH AS 

    BULK_SIZE CONSTANT BINARY_INTEGER := 10000;  
 
    CURSOR curEMP(p_dept_id VARCHAR2) IS
        SELECT EMP_ID, DEPT_ID, EMP_NAME
          FROM EMP
         WHERE DEPT_ID = p_dept_id
         ORDER BY EMP_ID ASC;
    
    TYPE typCurEmp IS TABLE OF curEMP%ROWTYPE ;
    TYPE typEmp2 IS TABLE OF emp2%ROWTYPE ;
 
    rdEmp typCurEmp;
    insEmp typEmp2 := typEmp2();
    updEmp typEmp2 := typEmp2();
    num number(10);
    
BEGIN

    OPEN curEMP('1000');

    LOOP
    
        FETCH curEMP BULK COLLECT INTO rdEmp LIMIT BULK_SIZE;
        EXIT WHEN rdEmp.COUNT = 0;
    
        insEmp.delete;
        updEmp.delete;
    
        FOR i in 1..rdEmp.COUNT LOOP
    
            SELECT count(1) 
              INTO num
              FROM emp2
             WHERE emp_id = rdEmp(i).emp_id; 
       
            IF num > 0 THEN
                updEmp.EXTEND;
                updEmp(updEmp.COUNT).emp_id := rdEmp(i).emp_id;
                updEmp(updEmp.COUNT).dept_id := rdEmp(i).dept_id;
                updEmp(updEmp.COUNT).emp_name := rdEmp(i).emp_name;
            ELSE
                insEmp.EXTEND;
                insEmp(insEmp.COUNT).emp_id := rdEmp(i).emp_id;
                insEmp(insEmp.COUNT).dept_id := rdEmp(i).dept_id;
                insEmp(insEmp.COUNT).emp_name := rdEmp(i).emp_name;
            END IF;
        END LOOP;

        FORALL i in 1..insEmp.COUNT 
            INSERT INTO emp2 values insEmp(i);
        
        FORALL i in  1..updEmp.COUNT
            UPDATE emp2 SET ROW = updEmp(i) Where emp_id = updEmp(i).emp_id;
        
        COMMIT;

    END LOOP;
    CLOSE curEMP;

END BULK_FETCH;

これで大量データの移行データも楽ちんチン!

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?