调试 Oracle 批量 DML 错误 - 如何确定导致错误的值?

Posted

技术标签:

【中文标题】调试 Oracle 批量 DML 错误 - 如何确定导致错误的值?【英文标题】:Debugging Oracle bulk DML error - how to determine which value caused the error? 【发布时间】:2011-11-16 20:14:19 【问题描述】:

我正在尝试调试在一个环境中发生的 DML 错误,而不是在其他环境中。设置是这样的:

我有大约 10 组 DML 操作(从远程表批量提取,批量插入本地表),其中两组给出 DML 错误,“无效数字”风格,另一组是“PL/SQL:数字或值错误:批量绑定:截断绑定”。

我尝试将数据复制到“良好”的环境中,但无法重现相同的错误。所以我现在正在尝试构建一个更强大的错误处理程序来捕获这些错误并帮助查明哪条数据给我带来了问题。

我的样子是这样的:

...
loop
    fetch c_some_data bulk collect into v_arr limit v_limit_size;

    forall i in 1..v_arr.count SAVE EXCEPTIONS
    insert into table_abc_1 values v_arr(i);
    exit when c_some_data%notfound;
end loop;
...
exception
    when X_DML_ERRORS then
        declare
            j integer;
        begin
            FOR j IN 1 .. SQL%BULK_EXCEPTIONS.COUNT LOOP
                begin
                   /*only print the KEY fields for this table,
                   this table has (I think) close to 20 fields*/
                   dbms_output.put_line('DML Bulk-operation error: ' ||
                                                         ' Error Code: '||SQLERRM(-SQL%BULK_EXCEPTIONS(j).ERROR_CODE)||'; '||
                                                         v_arr(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).stage||'; '||
                                                         v_arr(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).id||'; '||
                                                         v_arr(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).code||'; ')

                end;

            end loop;
        end;
    when others then
        PKG_EXCPTN.sp_generic_exception_handler;
end;

我确信我可以只打印所有列,但表很大(有些列超过 20 列)并且有 10 个代码块可能会出现此问题。它还需要有人查看消息中的每个值,看看它是否与列类型匹配(varchar2 与 number)。

有没有简单的方法来打印发生错误的字段和导致错误的值?

(使用 Oracle 10g)

【问题讨论】:

【参考方案1】:

您可以在 DML 语句中使用 LOG ERRORS INTO,这将允许您将错误和错误数据转储到表中,以便以后检查。

见:http://www.oracle-developer.net/display.php?id=329

和:http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_9014.htm#BGBDIGAH

【讨论】:

有趣...这将告诉我哪个字段中的哪个值导致了问题?我以前从未听说过这个功能。看起来它创建了一个新的登录表......我将不得不与 DBA 交谈,看看他是否对此感到满意。看起来我还必须用带有常规insert 语句的循环替换我当前的forall...insert,对吗?该代码最初是用forall...insert 编写的,因为它处理相当大的容量并且性能是一个问题。 嗯,所以我只是尝试使用没有表名的LOG ERROR(应该按照指定转到一个新的默认表,对吗?),当出现“表或视图不存在”错误时我编译。嗯? 好吧,我已经编译好了...必须先在单独的脚本中调用函数来创建表...现在我从 DBMS_ERRLOG 中收到“权限不足”错误...呃。 @FrustratedWithFormsDesigner 尝试创建一个error logging table by yourself 这是format BTW DML 错误日志记录与FORALL as well 配合得很好 我能够自己创建表格并使其正常工作。它看起来不像隔离 which 值会导致无效数字(或其他 DML)错误,但它仍然比手动为每个表、列和值进行 dbms_output'ing 更容易记录信息.谢谢!

以上是关于调试 Oracle 批量 DML 错误 - 如何确定导致错误的值?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查分配给模式、oracle 数据库中角色的对象的权限(DDL、DML、DCL)?

一个批量收集操作循环中的两个(或多个)DML

如何加速Oracle大批量数据处理?

Oracle中 “ORA-14551: 无法在查询中执行 DML 操作” 如何解决

解决 Oracle 中的“无法在查询中执行 DML”错误

Procedure-Function oracle