plsql
उपवाद सम्भालना
खोज…
परिचय
ओरेकल विभिन्न प्रकार के अपवाद पैदा करता है। आप आश्चर्यचकित हो सकते हैं कि कुछ अस्पष्ट संदेश के साथ आपका कोड रोकना कितना कठिन हो सकता है। अपने पीएल / एसक्यूएल कोड को आसानी से ठीक करने की क्षमता में सुधार करने के लिए सबसे निचले स्तर पर अपवादों को संभालना आवश्यक है। कभी भी एक अपवाद को "कालीन के नीचे" न छिपाएं, जब तक कि आप यहां केवल अपने लिए और किसी और को बनाए रखने के लिए अपने कोड का टुकड़ा नहीं रखते हैं।
उपवाद सम्भालना
अपवाद क्या है?
पीएल / एसक्यूएल में अपवाद एक प्रोग्राम निष्पादन के दौरान बनाई गई त्रुटि है।
हमारे पास तीन प्रकार के अपवाद हैं:
- आंतरिक रूप से परिभाषित अपवाद
- पूर्वनिर्धारित अपवाद
- उपयोगकर्ता-परिभाषित अपवाद
एक अपवाद हैंडलिंग क्या है?
अपवाद हैंडलिंग हमारे प्रोग्राम को चालू रखने की संभावना है, भले ही रनिंग त्रुटि दिखाई दे, उदाहरण के लिए कोडिंग गलतियों, हार्डवेयर विफलताओं। हम इसे अचानक से बाहर निकलने से बचें।
वाक्य - विन्यास
अपवाद अनुभाग के लिए सामान्य वाक्यविन्यास:
declare
declaration Section
begin
some statements
exception
when exception_one then
do something
when exception_two then
do something
when exception_three then
do something
when others then
do something
end;
एक अपवाद खंड PL / SQL ब्लॉक के अंत में होना चाहिए। PL / SQL हमें घोंसले के ब्लॉक का अवसर देता है, तो प्रत्येक ब्लॉक का अपना अपवाद अनुभाग हो सकता है:
create or replace procedure nested_blocks
is
begin
some statements
begin
some statements
exception
when exception_one then
do something
end;
exception
when exception_two then
do something
end;
यदि अपवाद को नेस्टेड ब्लॉक में उठाया जाएगा तो इसे आंतरिक अपवाद अनुभाग में संभाला जाना चाहिए, लेकिन अगर आंतरिक अपवाद अनुभाग इस अपवाद को नहीं संभालता है तो यह अपवाद बाहरी ब्लॉक के अपवाद अनुभाग में जाएगा।
आंतरिक रूप से परिभाषित अपवाद
आंतरिक रूप से परिभाषित अपवाद का नाम नहीं है, लेकिन इसका अपना कोड है।
इसका उपयोग कब करें?
यदि आप जानते हैं कि आपका डेटाबेस ऑपरेशन विशिष्ट अपवादों को बढ़ा सकता है जिनके नाम नहीं हैं, तो आप उन्हें नाम दे सकते हैं ताकि आप उनके लिए विशेष रूप से अपवाद हैंडलर लिख सकें। अन्यथा, आप उन्हें केवल others
अपवाद हैंडलर के साथ उपयोग कर सकते हैं।
वाक्य - विन्यास
declare
my_name_exc exception;
pragma exception_init(my_name_exc,-37);
begin
...
exception
when my_name_exc then
do something
end;
my_name_exc exception;
यह अपवाद नाम की घोषणा है।
pragma exception_init(my_name_exc,-37);
आंतरिक रूप से परिभाषित अपवाद के त्रुटि कोड को नाम असाइन करें।
उदाहरण
हमारे पास एक emp_id है जो एम्पायर टेबल में एक प्राथमिक कुंजी है और एक डिप्टी टेबल में एक विदेशी कुंजी है। अगर हम चाइल्ड रिकॉर्ड होने पर एम्प_ड को हटाने की कोशिश करते हैं, तो इसे कोड -2292 के साथ एक अपवाद के रूप में फेंक दिया जाएगा।
create or replace procedure remove_employee
is
emp_exception exception;
pragma exception_init(emp_exception,-2292);
begin
delete from emp where emp_id = 3;
exception
when emp_exception then
dbms_output.put_line('You can not do that!');
end;
/
ओरेकल प्रलेखन कहता है: "उपयोगकर्ता द्वारा घोषित नाम के साथ आंतरिक रूप से परिभाषित अपवाद अभी भी आंतरिक रूप से परिभाषित अपवाद है, न कि उपयोगकर्ता द्वारा परिभाषित अपवाद।"
पूर्वनिर्धारित अपवाद
पूर्वनिर्धारित अपवाद आंतरिक रूप से परिभाषित अपवाद हैं, लेकिन उनके नाम हैं। ओरेकल डेटाबेस इस प्रकार के अपवादों को स्वचालित रूप से बढ़ाता है।
उदाहरण
create or replace procedure insert_emp
is
begin
insert into emp (emp_id, ename) values ('1','Jon');
exception
when dup_val_on_index then
dbms_output.put_line('Duplicate value on index!');
end;
/
नीचे उनके कोड के साथ अपवाद नाम दिए गए हैं:
अपवाद का नाम | एरर कोड |
---|---|
कोई डेटा नहीं मिला | -1403 |
ACCESS_INTO_NULL | -6530 |
CASE_NOT_FOUND | -6592 |
ROWTYPE_MISMATCH | -6504 |
TOO_MANY_ROWS | -1422 |
ZERO_DIVIDE | -1476 |
ओरेकल वेब-साइट पर अपवाद नामों और उनके कोड की पूरी सूची।
उपयोगकर्ता परिभाषित अपवाद
जैसा कि नाम से पता चलता है कि उपयोगकर्ता परिभाषित अपवाद उपयोगकर्ताओं द्वारा बनाए गए हैं। यदि आप अपना स्वयं का अपवाद बनाना चाहते हैं, तो आपको निम्न करना होगा:
- अपवाद घोषित करें
- इसे अपने कार्यक्रम से उठाएं
- उसे पकड़ने के लिए उपयुक्त अपवाद हैंडलर बनाएँ।
उदाहरण
मैं श्रमिकों के सभी वेतन को अद्यतन करना चाहता हूं। लेकिन अगर कोई श्रमिक नहीं हैं, तो एक अपवाद बढ़ाएं।
create or replace procedure update_salary
is
no_workers exception;
v_counter number := 0;
begin
select count(*) into v_counter from emp;
if v_counter = 0 then
raise no_workers;
else
update emp set salary = 3000;
end if;
exception
when no_workers then
raise_application_error(-20991,'We don''t have workers!');
end;
/
इसका क्या अर्थ है raise
?
अपवाद डेटाबेस डेटाबेस द्वारा स्वचालित रूप से उठाया जाता है जब कोई आवश्यकता होती है, लेकिन यदि आप चाहते हैं, तो आप स्पष्ट रूप से किसी भी अपवाद को raise
उपयोग कर सकते हैं।
कार्यविधि raise_application_error(error_number,error_message);
- error_number -20000 और -20999 के बीच होना चाहिए
- error_message संदेश तब प्रदर्शित होता है जब त्रुटि होती है।
कस्टम अपवाद को परिभाषित करें, इसे बढ़ाएं और देखें कि यह कहां से आता है
इसे समझने के लिए, यहां एक फ़ंक्शन है जिसमें 3 अलग-अलग "गलत" व्यवहार हैं
- पैरामीटर पूरी तरह से बेवकूफ है: हम एक उपयोगकर्ता-परिभाषित अभिव्यक्ति का उपयोग करते हैं
- पैरामीटर में एक टाइपो है: हम Oracle मानक
NO_DATA_FOUND
त्रुटि का उपयोग करते हैं - एक और, लेकिन मामला नहीं संभाला
इसे अपने मानकों के अनुकूल बनाने के लिए स्वतंत्र महसूस करें:
DECLARE
this_is_not_acceptable EXCEPTION;
PRAGMA EXCEPTION_INIT(this_is_not_acceptable, -20077);
g_err varchar2 (200) := 'to-be-defined';
w_schema all_tables.OWNER%Type;
PROCEDURE get_schema( p_table in Varchar2, p_schema out Varchar2)
Is
w_err varchar2 (200) := 'to-be-defined';
BEGIN
w_err := 'get_schema-step-1:';
If (p_table = 'Delivery-Manager-Is-Silly') Then
raise this_is_not_acceptable;
end if;
w_err := 'get_schema-step-2:';
Select owner Into p_schema
From all_tables
where table_name like(p_table||'%');
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- handle Oracle-defined exception
dbms_output.put_line('[WARN]'||w_err||'This can happen. Check the table name you entered.');
WHEN this_is_not_acceptable THEN
-- handle your custom error
dbms_output.put_line('[WARN]'||w_err||'Please don''t make fun of the delivery manager.');
When others then
dbms_output.put_line('[ERR]'||w_err||'unhandled exception:'||sqlerrm);
raise;
END Get_schema;
BEGIN
g_err := 'Global; first call:';
get_schema('Delivery-Manager-Is-Silly', w_schema);
g_err := 'Global; second call:';
get_schema('AAA', w_schema);
g_err := 'Global; third call:';
get_schema('', w_schema);
g_err := 'Global; 4th call:';
get_schema('Can''t reach this point due to previous error.', w_schema);
EXCEPTION
When others then
dbms_output.put_line('[ERR]'||g_err||'unhandled exception:'||sqlerrm);
-- you may raise this again to the caller if error log isn't enough.
-- raise;
END;
/
एक नियमित डेटाबेस पर देना:
[WARN]get_schema-step-1:Please don't make fun of the delivery manager.
[WARN]get_schema-step-2:This can happen. Check the table name you entered.
[ERR]get_schema-step-2:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows
[ERR]Global; third call:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows
याद रखें कि दुर्लभ मामलों को संभालने के लिए अपवाद यहां हैं। मैंने उन अनुप्रयोगों को देखा जिन्होंने हर एक्सेस पर एक अपवाद उठाया, बस उपयोगकर्ता पासवर्ड पूछने के लिए, "कनेक्टेड नहीं" ... इतना अभिकलन बेकार।
हैंडलिंग त्रुटि त्रुटि अपवाद
प्रत्येक मानक ओरेकल त्रुटि एक त्रुटि संख्या के साथ जुड़ा हुआ है। यह अनुमान लगाना महत्वपूर्ण है कि आपके कोड में क्या गलत हो सकता है। किसी अन्य डेटाबेस के लिए कनेक्शन के लिए, यह हो सकता है:
-
-28000
खाता बंद है -
-28001
पासवर्ड समाप्त हो गया -
-28002
अनुग्रह अवधि -
-1017
गलत उपयोगकर्ता / पासवर्ड
डेटाबेस लिंक द्वारा उपयोग किए गए उपयोगकर्ता के साथ क्या गलत है, यह जांचने का एक तरीका है:
declare
v_dummy number;
begin
-- testing db link
execute immediate 'select COUNT(1) from dba_users@pass.world' into v_dummy ;
-- if we get here, exception wasn't raised: display COUNT's result
dbms_output.put_line(v_dummy||' users on PASS db');
EXCEPTION
-- exception can be referred by their name in the predefined Oracle's list
When LOGIN_DENIED
then
dbms_output.put_line('ORA-1017 / USERNAME OR PASSWORD INVALID, TRY AGAIN');
When Others
then
-- or referred by their number: stored automatically in reserved variable SQLCODE
If SQLCODE = '-2019'
Then
dbms_output.put_line('ORA-2019 / Invalid db_link name');
Elsif SQLCODE = '-1035'
Then
dbms_output.put_line('ORA-1035 / DATABASE IS ON RESTRICTED SESSION, CONTACT YOUR DBA');
Elsif SQLCODE = '-28000'
Then
dbms_output.put_line('ORA-28000 / ACCOUNT IS LOCKED. CONTACT YOUR DBA');
Elsif SQLCODE = '-28001'
Then
dbms_output.put_line('ORA-28001 / PASSWORD EXPIRED. CONTACT YOUR DBA FOR CHANGE');
Elsif SQLCODE = '-28002'
Then
dbms_output.put_line('ORA-28002 / PASSWORD IS EXPIRED, CHANGED IT');
Else
-- and if it's not one of the exception you expected
dbms_output.put_line('Exception not specifically handled');
dbms_output.put_line('Oracle Said'||SQLCODE||':'||SQLERRM);
End if;
END;
/