【问题标题】:compilation issue with execute immediate in Forall statement在 Forall 语句中立即执行的编译问题
【发布时间】:2013-10-14 07:14:21
【问题描述】:

请帮助我解决我面临的以下问题,我必须在 FORALL 中将数据插入到表中(表名使用变量值生成并且表已经创建)..

Declare
TYPE dept_data_rec IS RECORD
(
  Dept_no number,
  Dept_name varchar2(100),
  Dept_loc  Varchar2(20)
 );

TYPE nt_dept_data IS TABLE OF dept_data_rec ;

l_dept_data_nt nt_dept_data;

BEGIN

FORALL j IN 1..l_dept_data_nt.COUNT SAVE EXCEPTIONS
EXECUTE IMMEDIATE 'INSERT INTO '||l_get_dept_rec.dept_seq_no||'_Dept_Data  VALUES '||
l_dept_data_nt(j);
COMMIT;

编译此代码时出现以下错误: PLS-00306:调用“||”时参数的数量或类型错误

但是当代码使用实际的表名时它可以工作

FORALL j IN 1..l_dept_data_nt.COUNT SAVE EXCEPTIONS
INSERT INTO A1_dept_data VALUES
l_dept_data_nt(j);
COMMIT;

【问题讨论】:

  • 对。 l_dept_data_nt(j) 是行类型或记录类型;你只能连接一个字符串,或者可以转换为字符串的东西。我不认为你可以使用绑定变量来做到这一点,即使它被定义为%rowtype,但我不是 100% 确定。您可能需要查看dbms_sql。不过有人可能有更好的主意 *8-)
  • 谢谢..我觉得问题出在 l_dept_data_nt(j) 上,我也在下面尝试,但是同样的错误消息来了。 EXECUTE IMMEDIATE 'INSERT INTO A1_dept_DATA VALUES '||l_dept_data_nt(j);
  • 请提供l_dept_data_nt的声明。似乎是一个集合。问题是该集合的元素是标量还是复合数据类型?
  • 嗨 Nic,代码部分中添加了声明
  • 文档不清楚您是否可以使用 FORALL 来“更改”每行的表。我认为不会,因为这会带来 0 的性能优势(纯粹的语法优势)。

标签: plsql oracle11g bulkinsert dynamic-sql


【解决方案1】:

Oracle 10g -

在 11g 之前的 Oracle 版本中,您不能将 FORALLEXECUTE IMMEDIATE 一起使用,只能与 INSERTUPDATEDELETE 一起使用。

http://docs.oracle.com/cd/B13789_01/appdev.101/b10807/13_elems021.htm

这是一种特殊的语法

  1. 读起来像 FOR 循环但不是,并且
  2. PL/SQL 使用它来执行批量 DML 操作,并且只能使用确切的关键字,而不是使用动态 SQL 或任何其他代码。

Oracle 11g +

在 11g 中,取消了使用 EXECUTE IMMEDIATE 的限制。见http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/forall_statement.htm

但是,字符串中唯一允许的变量是USING 子句中单个数组的下标元素。

文档不清楚您是否可以使用FORALL 语法动态地“更改”每行的表。请记住,PL/SQL 使用FORALL 来执行批量 DML 操作,并且需要转到一个表才能产生任何性能优势。

上述问题的最佳性能解决方案

您应该创建两级数组,第一级定义哪个表,第二级定义该表的数据。

在表数组上使用普通的FOR 循环,并在该循环内使用特殊的FORALL 语法对一个表执行所有 DML。

【讨论】:

  • 文档不清楚单表限制是否实际被强制执行,或者这是否只是默默地导致性能下降!
猜你喜欢
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多