在DUP_VAL_ON_INDEX时继续迭代

时间:2014-03-07 08:49:10

标签: oracle

我有一个程序procedure1,如下所示,

表TESTTABLE123的值是,

enter image description here

create or replace procedure procedure1 as 
CURSOR TESTTABLE124_CUR IS SELECT *  FROM TESTTABLE123 ;
begin

     FOR i IN TESTTABLE124_CUR LOOP 
       BEGIN
        INSERT INTO TESTTABLE124 (select * from TESTTABLE123);

       EXCEPTION
      WHEN DUP_VAL_ON_INDEX  THEN
      DBMS_OUTPUT.PUT_LINE('duplicate value');
      CONTINUE;
      END ;
      END LOOP;
      commit;
end procedure1;

执行此程序时,我收到错误, An UPDATE or INSERT statement attempted to insert a duplicate key.

  1. 但是为什么连第一行都没有插入到第二个表中。

  2. 我的要求是如果发生错误,它应该继续迭代并插入即将到来的行。

3 个答案:

答案 0 :(得分:3)

问题是您尝试在每次迭代中插入所有行。在您的情况下,您只想在循环内插入一个行(逐行处理),这样如果失败只有一行失败,可以插入下一行。

CREATE OR REPLACE PROCEDURE procedure1 AS
   CURSOR TESTTABLE124_CUR IS
      SELECT * FROM TESTTABLE123;
BEGIN
   FOR i IN TESTTABLE124_CUR LOOP
      BEGIN
         INSERT INTO TESTTABLE124 VALUES (i.col1, i.col2...i.coln);      
      EXCEPTION
         WHEN DUP_VAL_ON_INDEX THEN
            DBMS_OUTPUT.PUT_LINE('duplicate value');         
      END;
   END LOOP;
   -- COMMIT; don't commit inside procedures
END procedure1;

或者,您只能插入不会引发异常的行(效率更高):

CREATE OR REPLACE PROCEDURE procedure1 AS
BEGIN
   INSERT INTO TESTTABLE124
      (SELECT * 
         FROM TESTTABLE123 t_old
        WHERE t_old.pk NOT IN (SELECT t_new.pk FROM TESTTABLE124 t_new));
   -- COMMIT; don't commit inside procedures
END procedure1;

pk替换为相应的唯一列名称。

答案 1 :(得分:1)

您可以使用RECORD变量中的RECORD隐式创建SELECT / CURSOR)将其作为FOR LOOP本身插入。< / p>

create or replace procedure procedure1 as 
CURSOR TESTTABLE124_CUR IS SELECT *  FROM TESTTABLE123 ;
begin

     FOR REC IN TESTTABLE124_CUR LOOP 
       BEGIN
        INSERT INTO TESTTABLE124 
            VALUES REC ;
        --- Just Specify the name.. But the column order should be same
       EXCEPTION
        WHEN DUP_VAL_ON_INDEX  THEN
            DBMS_OUTPUT.PUT_LINE('duplicate value');
            CONTINUE;
        END ;
      END LOOP;
      commit;
end procedure1;

答案 2 :(得分:0)

可以使用提示而不是异常处理:

INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(TESTTABLE124 , TESTTABLE124_PK) */
INTO TESTTABLE124 ...