我是PL / SQL的新手
我决定使用以下SQL将数千条记录插入表中。但是,将FORALL语句置于for循环外是否正确?
将FORALL语句移到循环块中更好吗?谢谢。
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 :(得分:0)
“在FOR循环块中移动FORALL语句是否更好”
没有。 FORALL是一个集合操作。您需要在每个工作单元执行一次,而不是每行执行一次。
“将数千条记录插入表格”
请记住,馆藏是在会话记忆中维护的。这意味着当您处理大量记录时,您需要更加注意内存管理。
所以你可能想分批工作,这样的事情:
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条记录的批次。
但是,实现示例的最有效方法仍然是
INSERT INTO table_a (book_id)
SELECT book_id
FROM books
WHERE book_category = 'PROGRAMMING'
and book_type = 'PLSQL';
答案 1 :(得分:0)
不,你的FORALL在正确的位置。当然,你的示例程序根本不需要这个,它可以写成:
BEGIN
INSERT INTO table_a (book_id)
SELECT book_id
FROM books
WHERE book_category = 'PROGRAMMING'
AND book_type = 'PLSQL';
END;
但我意识到你对学习FORALL概念感兴趣,而不是编写最简单的代码!
答案 2 :(得分:0)
在您的示例中,FORALL需要集合l_book_ids
作为输入。
在FOR循环中,集合尚未完全创建,因此您不能在其上使用FORALL。
FORALL是一个声明,正如APC所提到的,你无法将其分解为多个步骤 - 事实上这是它的优点 - 它可以快速完成工作。