[英]Create a generic PL SQL procedure to log Bulk Collect errors dynamically
最近在SQL了解到BULK COLLECT的使用,找到了一种处理DML语句产生异常的方法:
SET SERVEROUTPUT ON SIZE 99999;
--
DECLARE
--
bulk_errors exception;
PRAGMA exception_init(bulk_errors, -24381);
--
--
CURSOR cursEmployee IS
SELECT EMPLOYEE_ID, EMPLOYEE_NAME
FROM EMPLOYEE;
TYPE employee_table IS TABLE OF cursEmployee%rowtype;
employee_rec employee_table;
--
BEGIN
--
OPEN cursEmployee;
FETCH cursEmployee BULK COLLECT INTO employee_rec LIMIT 10000;
--
WHILE employee_rec.COUNT != 0 LOOP
--
FORALL indx IN INDICES OF employee_rec save exceptions
--
INSERT INTO EMPLOYEE (
EMPLOYEE_ID,
EMPLOYEE_NAME
)
VALUES (
employee_rec.EMPLOYEE_ID,
employee_rec.EMPLOYEE_NAME
);
--
COMMIT;
--
FETCH cursEmployee BULK COLLECT INTO employee_rec LIMIT 10000;
--
END LOOP;
exception when bulk_errors then
for i in 1 .. sql%bulk_exceptions.COUNT loop
dbms_output.put_line('Employee Id : ' || sql%bulk_exceptions(i).EMPLOYEE_ID);
dbms_output.put_line('Employee Id : ' || sql%bulk_exceptions(i).EMPLOYEE_NAME);
dbms_output.put_line('Error Message: '||sqlerrm(-sql%bulk_exceptions(i).error_code));
end loop;
CLOSE cursEmployee;
END;
/
然后我创建了一个通用过程来记录异常:
CREATE OR REPLACE PROCEDURE LOG_BULK_EXCEPTIONS IS
BEGIN
IF SQL%BULK_EXCEPTIONS.COUNT > 0 THEN
DBMS_OUTPUT.PUT_LINE(' Errors occured during a BULK COLLECT statement : ');
DBMS_OUTPUT.PUT_LINE(' Number of exceptions : ' || SQL%BULK_EXCEPTIONS.COUNT );
--
FOR i IN 1 .. SQL%BULK_EXCEPTIONS.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(' Error : ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
DBMS_OUTPUT.PUT_LINE('Backtrace : ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END LOOP;
--
END IF;
END;
/
我发现这种记录异常的方式有点受限:我们只是得到错误(数值,无法将 null 插入,等等...)。 我正在寻找一种方法来添加有关引发错误的 cursor 中的数据/特定元素的信息。
为此,我需要将一个列名作为参数传递给我的过程,并将它连接起来以获得这种语句:
dbms_output.put_line(' Internal Id : ' || sql%bulk_exceptions(i).MY_COLUMN_PARAMETER);
这样,我就可以在数据库中的任何地方使用这个日志记录程序,这太棒了。
有谁知道如何将字符串参数连接到这个“sql%bulk_exceptions(i).”并正确执行它?
是的,只要你想在原始收藏中添加什么,你就可以获得你正在寻找的东西。 sql%bulk_exceptions 集合有另一列 ERROR_INDEX。 它包含原始集合中行的索引。 这允许您通过以下方式引用该集合中的值
employee_rec(sql%bulk_exceptions(i).error_index).id;
employee_rec(sql%bulk_exceptions(i).error_index).name;
您的程序还有另一个问题。 您的异常块在处理批量收集的循环之外。 因此,您的批量缓冲区将仅在第一个缓冲区包含错误之前被处理; 不会处理后续缓冲区。 您可以通过在处理循环内创建一个块并在内部块内处理异常来避免这种情况。 此外,很高兴看到您努力实际关闭 cursor。但是,它位于异常块中,因此仅在出现异常时才执行。 有关每个示例,请参见此处。 因为我不想为演示创建超过 10000 行,所以我将批量限制减少到 3。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.