代码之家  ›  专栏  ›  技术社区  ›  Sathyajith Bhat ron tornambe

引发异常时继续在Oracle中插入

  •  3
  • Sathyajith Bhat ron tornambe  · 技术社区  · 15 年前

    我正在将数据从旧系统迁移到我们的新应用程序(运行在Oracle数据库10gr2上)。作为迁移的一部分,我正在编写一个脚本,它将数据插入到应用程序使用的表中。

    导入的数据行数达到数千行,并且源数据不干净(非空列中的意外空值等)。因此,在通过脚本插入数据的过程中,每当发生这种异常时,脚本都会突然结束,并回滚整个事务。

    有没有一种方法可以让我继续插入行干净的数据? 使用 NVL() COALESCE() 不是一个选项,因为我想记录导致错误的行,以便在下次传递时更正数据。

    编辑:我当前的过程有一个异常处理程序,我正在记录导致错误的第一行。插入是否可以继续而不终止,因为现在在第一个处理的异常上,过程终止执行。

    5 回复  |  直到 13 年前
        1
  •  5
  •   Shea    15 年前

    使用PLSQL,您可以在自己的事务中执行每个插入(在每个插入之后提交),并使用一个持续运行的异常处理程序记录或忽略错误。

        2
  •  9
  •   Gary Myers    15 年前

    如果数据量更大,那么在pl/sql中逐行处理可能会太慢。 在这种情况下,您可以使用DML错误日志记录,如前所述 here

    CREATE TABLE raises (emp_id NUMBER, sal NUMBER 
       CONSTRAINT check_sal CHECK(sal > 8000));
    
    EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('raises', 'errlog');
    
    INSERT INTO raises
       SELECT employee_id, salary*1.1 FROM employees
       WHERE commission_pct > .2
       LOG ERRORS INTO errlog ('my_bad') REJECT LIMIT 10;
    
    SELECT ORA_ERR_MESG$, ORA_ERR_TAG$, emp_id, sal FROM errlog;
    
    ORA_ERR_MESG$               ORA_ERR_TAG$         EMP_ID SAL
    --------------------------- -------------------- ------ -------
    ORA-02290: check constraint my_bad               161    7700
     (HR.SYS_C004266) violated
    
        3
  •  4
  •   user272735    13 年前

    试试这个:

    for r_row in c_legacy_data loop
      begin
        insert into some_table(a, b, c, ...)
        values (r_row.a, r_row.b, r_row.c, ...);
      exception
        when others then 
          null;  /* or some extra logging */
      end;
    end loop;
    
        4
  •  1
  •   Sai Ganesh    15 年前
    DECLARE
       cursor;
    BEGIN
        loop for each row  in cursor
          BEGIN  -- subBlock begins 
             SAVEPOINT startTransaction;  -- mark a savepoint
     -- do whatever you have do here
             COMMIT;         
          EXCEPTION
             ROLLBACK TO startTransaction;  -- undo changes
          END;  -- subBlock ends
       end loop;
    END;
    
        5
  •  0
  •   Mark Roddy    15 年前

    如果使用sqlldr,可以指定继续加载数据,所有“坏”数据将被跳过并记录在单独的文件中。