BULK 收集和 FORALL 两次插入数据

Posted

技术标签:

【中文标题】BULK 收集和 FORALL 两次插入数据【英文标题】:BULK Collect and FORALL inserting data twice 【发布时间】:2013-10-09 14:16:48 【问题描述】:

在下方需要帮助!

我的代码有 2 个游标,从第一个游标我得到不同的值,并从第二个游标一个接一个地将它们传递给第二个游标(参数化),我得到结果集,我使用 BULK COLLECT 和全部。

我有一个场景,如果在第二个游标中找不到数据,则从第一个游标中获取值,然后将集合中的相同值插入表中两次。

例如:

for emp : 1 我有两个部门 2 和 3 被插入到 table-perfect 对于 emp 2:没有部门 - 再次插入 2 和 3 - 错误。

请帮帮我,如果在第二个游标中找不到记录,我不想从集合中插入旧记录。

我在这里发现了一个问题,当我从 BULK collect stmt 中删除 LOOP 和 LIMIT 时,它工作正常,但是当我添加 LOOP 和 LIMIT 时,它会插入两次数据。

我应该使用 .Delete() 方法吗?在哪里 ?

下面是示例代码

  DECLARE

  CURSOR emp_cur IS  
  SELECT DISTINCT emp_id from employee;

  CURSOR get_dept_cur(emp IN VARCHAR2) IS
  SELECT DISTINCT dept from department where dpt_emp_id=emp;

  TYPE nt_emp_metadata IS TABLE OF get_dept_cur%ROWTYPE;
  l_data_array nt_emp_metadata ;

BEGIN
   OPEN emp_cur ;

   LOOP FETCH emp_cur INTO l_emp;
      EXIT WHEN emp_cur %NOTFOUND;     

       OPEN get_dept_cur(l_emp);
        LOOP FETCH get_dept_cur BULK COLLECT INTO l_data_array LIMIT 100;
          FORALL i IN 1..l_data_array.COUNT
          INSERT INTO ABC VALUES l_data_array(i);
     EXIT WHEN get_dept_cur%NOTFOUND;
        END LOOP;
   COMMIT;
        CLOSE get_dept_cur;

   END LOOP;
   CLOSE emp_cur ;
 END;

【问题讨论】:

您是否尝试使用 dbms_output 进行一些调试来调查问题? l_metadata_array 来自哪里?同样在这一点上,带有 CREATE TABLEINSERT 和带有变量声明的完整 DECLARE..END 块的完整示例将有助于重现。 嗨,文森特,这是错别字……它的 l_data_array 不是嵌套表类型的 l_metadata_array。我修改了代码。 【参考方案1】:

有什么问题?您在 ABC 中得到重复记录?那是因为您可以为不同的员工拥有相同的deptvalue。如果您最终想在 ABC 中插入 dept 的所有 emps,这样做会更容易:

INSERT INTO ABC
SELECT d.dept
FROM employee e
JOIN department d
ON e.dept=d.dept
GROUP BY d.dept;

记住:光标是万恶之源 :)

【讨论】:

以上是关于BULK 收集和 FORALL 两次插入数据的主要内容,如果未能解决你的问题,请参考以下文章

Oracle PL/SQL 如何输出在 FORALL 语句中进行了多少次插入

如何提高 FORALL 插入例程的性能?

FORALL和BULK COLLECT

oracle 优化之批量处理bulk correct 和 forall

ORACLE批量绑定FORALL与BULK COLLECT

使用 PL/SQL 使用 forall 语法批量插入