所以我有这个项目,我正在工作,我注意到很多人使用INSERT INTO SELECT方法:
INSERT INTO candy_tbl (candy_name,
candy_type,
candy_qty)
SELECT food_name,
food_type,
food_qty
FROM food_tbl WHERE food_type = 'C';
但是,我使用以下游标方法:
FOR rec IN ( SELECT
food_name,
food_type,
food_qty
FROM food_tbl WHERE food_type = 'C')
LOOP INSERT INTO candy_tbl(candy_name,
candy_type,
candy_qty)
VALUES(rec.food_name,
rec.food_type,
rec.food_qty)
END LOOP;
这将进入PL / SQL包。我的问题是,这通常是首选的'方法何时?我通常选择游标方法,因为它为异常处理提供了更多的灵活性。但是,在插入大量记录时,我可以看到它可能是一个性能问题。
答案 0 :(得分:1)
FOR LOOP需要从CURSOR获取每一行。循环中的INSERT将由1进行.PLSQL在PLSQL引擎中运行,SQL在SQL引擎中运行,因此FOR LOOP: - 在PLSQL引擎中运行 - 将查询发送到SQL引擎以执行查询并打开游标,然后切换回PLSQL引擎 - 每个循环从CURSOR执行FETCH,然后执行INSERT意义返回SQL引擎然后返回到PLSQL引擎
SQL和PLSQL之间的每次切换以及每个FETCH都很昂贵。
INSERT INTO SELECT将被发送到SQL引擎一次并在那里运行直到完成然后再回到PLSQL。
存在其他优点,但这是两种方法之间主要的PLSQL差异。
答案 1 :(得分:0)
Insert as select具有默认sql的优点,因此,使用这种指令的PL / SQL并不完全是人们常见的。 使用游标比选择插入更灵活,通常更像verborragic。 我个人建议您尽可能使用Insert作为select,这样可以避免为项目增加复杂性,普通用户阅读代码会更简单。请记住,许多知道SQL但很少知道PL / SQL的人。
在性能方面,insert as select似乎更具性能,但我从来没有见过一个和另一个之间有任何显着差异。
答案 2 :(得分:0)
第一个更快,因为它基本上是单个事务,也就是基于集合的处理。
后者按行进行操作,对于非常大的表格,性能会有很大差异。
答案 3 :(得分:0)
如果您确实需要游标处理的灵活性但性能更好,则可以使用第三个中间选项 - BULK COLLECT和FORALL以及保存例外选项。然而,权衡更多是代码复杂性。以下是基本结构。
declare
exception error_in_forall ;
pragma exception_init (error_in_forall, -24381);
cursor c_select is ( select ... ) ;
type c_array_type table of c_select%rowtype;
v_select_data c_array_type ;
begin
open c_select;
loop
fetch c_select
bulk collect
into v_select_data;
forall rdata in v_select_data.first .. v_select_data.last save exceptions
insert into ( ... ) values (v_select_data(rdata).column ... ) ;
exceptions
when error_in_forall then
<Process Oracle generated bulk error collection >
end ;
如果在执行Insert期间发生任何错误,则完成后,异常将触发一次。 Oracle构建了一个SQL%BULK_EXCEPTIONS集合,其中包含索引值和每个的错误代码。有关详细信息,请参阅适用于您的版本的PL / SQL语言参考。