我的软件包正在提出ORA-06502:PL / SQL:数字或值错误。
我可以在catch块中添加一些代码来识别哪些数据未成功插入哪个数据?
现在我只有:
WHEN OTHERS
...log SQLCODE and SQLERRM...
RAISE PROGRAM ERROR;
RETURN;
谢谢。
答案 0 :(得分:1)
让我们说你有这样的情况:
CREATE TABLE MY_TABLE (PK NUMBER PRIMARY KEY, COL_A NUMBER(2), COL_B NUMBER(2));
BEGIN
INSERT INTO MY_TABLE
SELECT LEVEL AS PK, ROUND(100*DBMS_RANDOM.NORMAL) AS COL_A, ROUND(100*DBMS_RANDOM.NORMAL) AS COL_B
FROM dual
CONNECT BY LEVEL < 20;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE (DBMS_UTILITY.FORMAT_ERROR_STACK);
DBMS_OUTPUT.PUT_LINE (DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END;
ORA-01438: value larger than specified precision allowed for this column
ORA-06512: at line 2
显然,您既不知道产生错误的行也不知道列。找到它的一种方法是这一个:
CREATE TABLE MY_TABLE_TEMP AS
SELECT LEVEL AS PK, ROUND(100*DBMS_RANDOM.NORMAL) AS COL_A, ROUND(100*DBMS_RANDOM.NORMAL) AS COL_B
FROM dual
CONNECT BY LEVEL < 20;
DECLARE
sqlstr VARCHAR2(1000);
BEGIN
FOR aRow IN (SELECT * FROM MY_TABLE_TEMP) LOOP
INSERT INTO MY_TABLE (PK) VALUES (aRow.PK);
FOR aCol IN (SELECT * FROM user_tab_cols WHERE table_name = 'MY_TABLE_TEMP') LOOP
BEGIN
sqlstr := 'UPDATE MY_TABLE a SET '||aCol.column_name||' = (SELECT '||aCol.column_name||' FROM MY_TABLE_TEMP b WHERE a.PK = b.PK) WHERE a.PK = :pk';
EXECUTE IMMEDIATE sqlstr USING aRow.PK;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE ( 'Error at line '||aRow.PK||' for column '||aCol.column_name ||' -> '||SQLERRM);
END;
END LOOP;
DBMS_OUTPUT.PUT_LINE ( 'Line '||aRow.PK||' -> OK');
END LOOP;
END;
Line 1 -> OK
Line 2 -> OK
Error at line 3 for column COL_B -> ORA-01438: value larger than specified precision allowed for this column
Line 3 -> OK
Error at line 4 for column COL_A -> ORA-01438: value larger than specified precision allowed for this column
Line 4 -> OK
Error at line 5 for column COL_A -> ORA-01438: value larger than specified precision allowed for this column
Line 5 -> OK
Error at line 6 for column COL_A -> ORA-01438: value larger than specified precision allowed for this column
Line 6 -> OK
Error at line 7 for column COL_B -> ORA-01438: value larger than specified precision allowed for this column
Line 7 -> OK
Error at line 8 for column COL_A -> ORA-01438: value larger than specified precision allowed for this column
Error at line 8 for column COL_B -> ORA-01438: value larger than specified precision allowed for this column
Line 8 -> OK
Error at line 9 for column COL_A -> ORA-01438: value larger than specified precision allowed for this column
Line 9 -> OK
Error at line 10 for column COL_B -> ORA-01438: value larger than specified precision allowed for this column
Line 10 -> OK
Line 11 -> OK
Error at line 12 for column COL_B -> ORA-01438: value larger than specified precision allowed for this column
Line 12 -> OK
Line 13 -> OK
Line 14 -> OK
Line 15 -> OK
Line 16 -> OK
Error at line 17 for column COL_B -> ORA-01438: value larger than specified precision allowed for this column
Line 17 -> OK
Line 18 -> OK
Error at line 19 for column COL_A -> ORA-01438: value larger than specified precision allowed for this column
Error at line 19 for column COL_B -> ORA-01438: value larger than specified precision allowed for this column
Line 19 -> OK
答案 1 :(得分:0)
多次阅读以下引文,直到您完全理解为止。
当其他人几乎总是一个BUG,除非立即跟进 通过RAISE。
WHEN OTHERS
隐藏错误的来源。
WHEN OTHERS
会破坏程序调用的原子性。
请注意,对于错误, RAISE –> CATCH –> HANDLE
因此,首先删除所有异常处理程序,然后重新执行PL / SQL块。错误堆栈将包含正确的行号和其他错误详细信息。
阅读https://lalitkumarb.wordpress.com/2014/05/02/when-others-then-null-a-bug/
例如,
SQL> CREATE OR REPLACE PROCEDURE p_test_others(i_val IN VARCHAR2) AS
2 o_val NUMBER;
3 BEGIN
4 SELECT i_val INTO o_val FROM dual;
5 DBMS_OUTPUT.PUT_LINE(o_val);
6 EXCEPTION
7 WHEN OTHERS THEN
8 DBMS_OUTPUT.PUT_LINE('SQLCODE: '||SQLCODE);
9 DBMS_OUTPUT.PUT_LINE('Message: '||SQLERRM);
10 RAISE;
11 END;
12 /
Procedure created
SQL>
SQL> BEGIN
2 p_test_others('a');
3 END;
4 /
SQLCODE: -6502
Message: ORA-06502: PL/SQL: numeric or value error: character to number conversion error
BEGIN
p_test_others('a');
END;
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "P_TEST_OTHERS", line 10
ORA-06512: at line 2
否则,
要记录错误,请使用:
获取调用堆栈。
例如,
SQL> declare
2 v1 integer := 1;
3 v2 integer := 0;
4 v3 integer;
5 procedure p1 (v1 in integer, v2 in integer, v3 out integer) is
6 begin
7 v3 := v1 / v2;
8 end;
9 procedure p2 (v1 in integer, v2 in integer, v3 out integer) is
10 begin
11 p1 (v1, v2, v3);
12 end;
13 begin
14 p2 (v1, v2, v3);
15 exception
16 when others then
17 dbms_output.put_line ('---------------------');
18 dbms_output.put_line ('This is what you record in log table:');
19 dbms_output.put (dbms_utility.format_error_stack);
20 dbms_output.put (dbms_utility.format_error_backtrace);
21 dbms_output.put_line ('---------------------');
22 raise;
23 end;
24 /
---------------------
This is what you record in log table:
ORA-01476: divisor is equal to zero
ORA-06512: at line 7
ORA-06512: at line 11
ORA-06512: at line 14
---------------------
declare
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at line 22
更新每个OP的请求
带有异常块的,行号将转到异常处理程序的行号。
SQL> BEGIN
2 INSERT INTO t
3 (A
4 ) VALUES
5 ('one'
6 );
7 EXCEPTION
8 WHEN OTHERS THEN
9 RAISE;
10 END;
11 /
BEGIN
*
ERROR at line 1:
ORA-12899: value too large for column "LALIT"."T"."A" (actual: 3, maximum: 1)
ORA-06512: at line 9
SQL>
没有异常阻止,您可以使用错误来源的正确行号:
SQL> BEGIN
2 INSERT INTO t
3 (A
4 ) VALUES
5 ('one'
6 );
7 END;
8 /
BEGIN
*
ERROR at line 1:
ORA-12899: value too large for column "LALIT"."T"."A" (actual: 3, maximum: 1)
ORA-06512: at line 2
SQL>
因此,错误堆栈会告诉您schame
,table_name
,column_name
以及其他详细信息,例如允许的最大尺寸和实际尺寸。
对于更具体或自定义的错误记录,请使用异常块中的所有必需列名编写您自己的代码,以便在这些列中插入值时记录错误。