哪个是批量插入Oracle数据库的更好选择?一个FOR Cursor循环就像
DECLARE
CURSOR C1 IS SELECT * FROM FOO;
BEGIN
FOR C1_REC IN C1 LOOP
INSERT INTO BAR(A,
B,
C)
VALUES(C1.A,
C1.B,
C1.C);
END LOOP;
END
Run Code Online (Sandbox Code Playgroud)
或简单的选择,如:
INSERT INTO BAR(A,
B,
C)
(SELECT A,
B,
C
FROM FOO);
Run Code Online (Sandbox Code Playgroud)
任何一个特定原因要么更好?
Jos*_*ein 30
我建议使用Select选项,因为游标需要更长时间.
对于必须修改查询的任何人来说,使用Select也更容易理解
Jef*_*emp 22
一般的经验法则是,如果您可以使用单个SQL语句而不是使用PL/SQL来执行此操作,则应该这样做.它通常会更有效率.
但是,如果需要添加更多过程逻辑(出于某种原因),则可能需要使用PL/SQL,但是应该使用批量操作而不是逐行处理.(注意:在Oracle 10g及更高版本中,您的FOR循环将自动使用BULK COLLECT一次获取100行;但是您的insert语句仍将逐行完成).
例如
DECLARE
TYPE tA IS TABLE OF FOO.A%TYPE INDEX BY PLS_INTEGER;
TYPE tB IS TABLE OF FOO.B%TYPE INDEX BY PLS_INTEGER;
TYPE tC IS TABLE OF FOO.C%TYPE INDEX BY PLS_INTEGER;
rA tA;
rB tB;
rC tC;
BEGIN
SELECT * BULK COLLECT INTO rA, rB, rC FROM FOO;
-- (do some procedural logic on the data?)
FORALL i IN rA.FIRST..rA.LAST
INSERT INTO BAR(A,
B,
C)
VALUES(rA(i),
rB(i),
rC(i));
END;
Run Code Online (Sandbox Code Playgroud)
以上功能可以最大限度地减少SQL和PL/SQL之间的上下文切换.Oracle 11g还具有对记录表的更好支持,因此您不必为每列都有单独的PL/SQL表.
此外,如果数据量非常大,则可以更改代码以批量处理数据.
像你的第二个选项一样简单的插入/选择是更可取的.对于第一个选项中的每个插入,您需要从pl/sql到sql的上下文切换.使用trace/tkprof运行每个并检查结果.
如果像迈克尔提到的那样,你的回滚无法处理声明,那么让你的dba给你更多.磁盘很便宜,而在多次传递中插入数据所产生的部分结果可能非常昂贵.(插入几乎没有撤消.)