使用 PL/SQL 使用 forall 语法批量插入
Posted
技术标签:
【中文标题】使用 PL/SQL 使用 forall 语法批量插入【英文标题】:Bulk insert with forall syntax using PL/SQL 【发布时间】:2018-03-26 07:43:16 【问题描述】:我习惯使用 T-SQL,但目前我正在使用 PL/SQL 进行项目,因此语法有时会有点不同。
现在,我正在尝试在数据库中插入大约 5000 条记录。这将通过 12 个不同的连接发生。 (我有 12 个 XML 不同的 XML 文件,我想在相应的表中插入每个 XML 的所有数据)
我的第一个想法是为每个插入生成一个新的 INSERT INTO
查询,但我猜这会带来一些真正的性能问题。
接下来我读到了INSERT ALL INTO <table_name>
,但我不确定这是否能解决性能问题?
最后,我读到FORALL
会在执行批量插入时显着提高速度。 (http://www.dba-oracle.com/oracle_news/news_plsql_forall_performance_insert.htm)
不幸的是,由于我的 PLSQL 知识还不是很好,所以我不知道如何解决这个问题。
我想做一些事情:
FORALL i IN 1..10
INSERT INTO DELETEME (ID, NAME) VALUES (i, 'name' + i);
这是我的表结构:
ID NUMBER(10,0)
NAME VARCHAR2(255 BYTE)
这就是我得到的:
Error starting at line : 2 in command -
INSERT INTO DELETEME (ID, NAME) VALUES (i, 'name' + i)
Error at Command Line : 2 Column : 61
Error report -
SQL Error: ORA-00984: column not allowed here
00984. 00000 - "column not allowed here"
*Cause:
*Action:
使用 FORALL 批量插入最简单的方法是什么? 或者你们知道有什么好的选择吗?
【问题讨论】:
【参考方案1】:您的代码中有几个错误。一个是简单的语法错误,试试
... VALUES (i, 'name' || i);
在 Oracle 中,字符串由 ||
连接,而不是由 +
(也不是 &
)
除此之外,FORALL
用于 PL/SQL 表。可以这样运行
DECLARE
TYPE nameTable IS TABLE OF INTEGER;
names nameTable;
BEGIN
names := nameTable(10,20,30,40);
FORALL i IN INDICES OF names
INSERT INTO DELETEME (ID, NAME) VALUES (names(i), 'name' ||names(i) );
END;
如果您只需要一个简单的序列,您也可以运行
INSERT INTO DELETEME (ID, NAME)
SELECT LEVEL, 'name' || LEVEL
FROM dual
CONNECT BY LEVEL <= 10;
【讨论】:
此时我遇到了两个错误。第一个声称在第 1 行有一个未知命令(FORALL i IN 1..10)。这可能是版本问题吗? 第二个错误表示第 59 列有错误(就在最后一个 i 之前和连接之后 (|| i
)。说的和以前一样:这里不允许列。
来自 Oracle 文档:循环的每次迭代都必须在其 VALUES 或 WHERE 子句中使用来自一个或多个集合的值。
@Rene, names(i)
是“来自其 VALUES [...] 子句中的一个 [...] 集合的值”
设法让它与这个和 cmets 一起工作。以为我不明白为什么需要在 VALUES 子句中使用一个或多个集合的值。以上是关于使用 PL/SQL 使用 forall 语法批量插入的主要内容,如果未能解决你的问题,请参考以下文章
Oracle pl/sql forall:如何计算表空间已满(1654)错误的实际插入行数
如何在 PL/SQL 中使用 BULK COLLECT 和 FORALL 替换 CURSOR FOR LOOP?
使用 FORALL 和 RETURNING 插入表时如何获取 ROWID