2017-07-11 28 views
0

私はPL/SQLを初めて使用しています。
次のSQLを使用して、何千ものレコードをテーブルに挿入することに決めました。しかし、FORALL文をforループの外側に置くのは正しいですか?
forループブロック内でFORALL文を移動する方が良いですか?ありがとうございました。FORALLをforループの外側に配置する必要がありますか?

DECLARE 

    CURSOR books_cur 
    IS 
    SELECT book_id, book_type 
    FROM books 
    WHERE book_category = 'PROGRAMMING'; 

    TYPE book_ids_t IS TABLE OF 
    books.book_id%TYPE; 

    l_book_ids book_ids_t := book_ids_t(); 

BEGIN 
    FOR i IN books_cur LOOP 
    IF(i.book_type = 'PLSQL') THEN 
     l_book_ids.EXTENDS; 
     l_book_ids(l_book_ids.LAST) := i.book_id; 
    END IF; 
    END LOOP; 

    FORALL i IN l_book_ids.FIRST..l_book_ids.LAST 
    INSERT INTO table_a (book_id) VALUES l_book_ids(i); 
END; 
+0

btw 'if'条件の括弧の必要はありません。彼らは何かを壊すことはありませんが、混乱し、コンパイラはそれらを無視します。 –

答えて

0

号FORALL "それは、より良いループブロックの内側のFORALL文を動かすことである" 集合演算です。 1つの行につき1回ではなく、作業単位ごとに1回実行する必要があります。

「をテーブルにレコードの数千人を挿入する」

コレクションがセッションメモリに維持されていることを覚えておいてください。つまり、膨大な数のレコードを扱う際には、メモリ管理を意識する必要があります。

BEGIN 
    FOR i IN books_cur LOOP 
     IF(i.book_type = 'PLSQL') THEN 
      l_book_ids.EXTENDS; 
      l_book_ids(l_book_ids.LAST) := i.book_id; 
     END IF; 
     if l_book_ids.count() = 1000 -- say 
     then 
      FORALL i IN l_book_ids.FIRST..l_book_ids.LAST 
       INSERT INTO table_a (book_id) VALUES l_book_ids(i); 
      l_book_ids.delete(); 
     end if; 
    END LOOP; 
    FORALL i IN l_book_ids.FIRST..l_book_ids.LAST 
     INSERT INTO table_a (book_id) VALUES l_book_ids(i);  
END; 

コードのこのバージョンは、1000年のバッチでレコードを挿入する可能性がある最後のバッチをキャッチする補足FORALL文で:

だからあなたは、バッチで動作するように、このような何かをしたいことがあり1000レコード未満であること。

しかし、あなたの例を実装するための最も効率的な方法はありません、あなたのFORALLが正しい場所にある

INSERT INTO table_a (book_id) 
SELECT book_id 
FROM books 
WHERE book_category = 'PROGRAMMING' 
and book_type = 'PLSQL'; 
+0

あなたは、私が心配しているのはメモリの使用量です。どうもありがとうございます。 –

0

まま。もちろん、すべてでこれを必要としないあなたの例のプログラムは、それは次のように記述することができます

BEGIN 
INSERT INTO table_a (book_id) 
SELECT book_id 
    FROM books 
    WHERE book_category = 'PROGRAMMING' 
     AND book_type = 'PLSQL'; 
END; 

しかし、私はあなたがFORALLの概念を学ぶのではなく、最も簡単なコードを書くことに興味がある実現します!

0

あなたの例では、FORALLはコレクションl_book_idsを入力する必要があります。 FORループ内では、コレクションはまだ完全には作成されていないため、FORALLを使用することはできません。 FORALLはAPCの言葉通り、複数のステップに分割することはできません。実際には、これが利点です。

関連する問題