2009-06-30 54 views
3

我工作的数据的迁移从旧系统到我们的新的应用程序(在Oracle数据库10gR2中运行)。作为迁移的一部分,我正在研究一个脚本,该脚本将数据插入到应用程序使用的表中。继续在插入时,甲骨文将引发异常

被导入的数据的行数运行到数千,并且源数据是不干净(在NOT NULL列意想不到空值,等等)。因此,在通过脚本插入数据时,无论何时发生此类异常,脚本都会突然结束,并且整个事务将回滚。

有没有一种方法,通过它我可以继续为其行是干净的数据的插入? 使用NVL()COALESCE()是不是一种选择,因为我想记录导致错误,这样的数据可以为下一次被修正的行。

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

回答

5

使用PLSQL可以执行在自己的事务每个插入(每次提交后)和日志或忽略的后果就是会异常处理程序错误。

+0

异常处理程序捕获的第一个错误,然后从程序退出。我如何避免它退出? – Sathya 2009-06-30 20:34:16

+1

@Arnshea是正确的 - 把插入它自己的块内:BEGIN insert ... EXCEPTION handle_exception END; – DCookie 2009-06-30 20:59:58

0

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

4

试试这个:

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; 
1
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; 
9

如果数据量较高,一行一行地处理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