[英]Which command raised the exception?
是否存在像SQLERRM
或SQLCODE
這樣的變量來保存引發錯誤的語句?
例:
/*
if some error raised from this code
and I want to know which statement cause the failure..
I wish to use some oracle varaible to know it
*/
begin
select * from t1;
select * from t2;
exception when others
dbms_output.put_line(sqlerrm || ' raised from this statement:' || <some_variable>;
end;
-- excepted result: no data found raised from this statement: select * from t2
簡單的答案,不。 通過定義異常處理程序,您將丟失一些信息。 對於未處理的異常,您會收到一條包含行號的錯誤消息。 但是顯然我們需要處理錯誤,記錄錯誤等。因此,沒有行號是很垃圾的。
幸運的是,有兩種選擇。 在舊版本的Oracle中,我們可以使用dbms_utility.format_error_backtrace()
和dbms_utility.format_error_stack()
獲得一些有用的信息,包括行號。 它非常笨拙,並且(特別是用於回溯)非常冗長。
在Oracle 12c中,我們得到了一個專門用於PL / SQL調用堆棧的完整軟件包:UTL_CALL_STACK。 它是一盒位,需要多次調用才能得到,但是我們可以使用unit_line()
檢索特定的行號。 蒂姆·霍爾(Tim Hall)對新功能進行了典型的精美介紹。 了解更多 。
要考慮的另一件事是良好的程序設計如何解決此問題。 特別是單一責任原則 。 這是程序設計的基本准則:程序單元應該做一件事。 如果我們問“通過此錯誤執行哪個命令”的問題,則可能表明我們違反了SRP。
讓我們辭職代碼,使其遵循以下設計原則:
declare
type nt1 is table of t1%rowtype;
type nt2 is table of t2%rowtype;
l_t1 nt1;
l_t2 nt2;
x_t1_ndf exception;
x_t2_ndf exception;
function get_t1 return nt1 is
return_value nt1;
begin
select *
bulk collect into return_value
from t1;
if return_value.count() = 0 then
raise x_t1_ndf;
end if;
return return_value;
end get_t1;
function get_t2 return nt2 is
return_value nt2;
begin
select *
bulk collect into return_value
from t2;
if return_value.count() = 0 then
raise x_t2_ndf;
end if;
return return_value;
end get_t2;
begin
l_t1 := get_t1;
l_t2 := get_t2;
exception
when x_t1_ndf then
dbms_output.put_line('T1 has no data');
when x_t2_ndf then
dbms_output.put_line('T2 has no data');
end;
顯然,鍵入的內容比原始代碼多,但是部分原因是,此玩具是完整的工作代碼,與您發布的代碼不同。 同樣在現實生活中,這些模塊將是離散的單元,而不是匿名塊中的私有功能,因此我們可以在其他多個程序中重復使用它們。
dbms_output.put_line()
也不是處理異常的正確方法,但是我已經離開了,因為這就是您的代碼所做的事情。
沒有內置功能可用於此目的。
一種方法是通過處理單個語句的異常,例如(偽代碼):
declare
err varchar2(100);
myException exception;
begin
...
begin
select * from t1;
exception
when others then
err := 'Error in select * from t1: ' || sqlerrm;
raise myException
end;
begin
select * from t2;
exception
when others then
err := 'Error in select * from t2: ' || sqlerrm;
raise myException
end;
...
exception
when myException then
dbms_output.put_line(err);
when others then
dbms_output.put_line('Unhandled exception: ' || sqlerrm);
end;
對於更多的東西, 這可能非常有用。
對多個語句使用單個異常處理程序總是會掩蓋導致錯誤的語句。
相反,您可以使用Local變量(Locator)來跟蹤語句執行,如下所示:
DECLARE
err_stmt NUMBER:= 1; -- Indicates 1st SELECT statement
BEGIN
SELECT ... -- Statement 1
err_stmt := 2; -- Indicates 2nd SELECT statement
SELECT ... -- Statement 2
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(sqlerrm || ' raised from this statement number:' || err_stmt;
END;
干杯!!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.