版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
一、一個實例
Commit;
createorreplaceprocedurePROCSUNHONGBOMONCHNL(timvarchar2)is
timestvarchar(8);
timdayvarchar(33);
sqlsqlvarchar(6666);
no_resultEXCEPTION;
begin
Commit;
selectto_char(sysdatc,'yyyymmddHU24mi3s1)timaintotimdayfromdual;
selectto_char(add_months(sysda:e,-l),'yyyymm')monintotimestfromdual;
selecttimmonintotimestfromdual;
executeimmediate'deleterepor:.wo_sunhongbo_chnlwhereraon=*|tim;
Commit;
/?I,添加所需要的列realcharge+time,如果有就拋出異常后繼續(xù)執(zhí)行**********/
BEGIN
executeimmediate1altertabicshiywl1.tmyaddreal_charge*||tim|1varchar2(66)1;
EXCEPTION
WHENno.resultTHEN
DBMS_OUTPUT.PUTJJNE('你的數(shù)據(jù)更新語句失敗了!’);
WHENOTHERSTHEN
DBMS_OUTPL'T.PUTJINE('你的數(shù)據(jù)更新語句!已經(jīng)存在該列1:'IItim);
END;
executeimmediate1updateshiywl1.tmysetreal_charge||tim||'=null';
Commit;
Commit;
dbms_output.put_line('timest:'||timestI|';tim:'I|tim||';timest:'|Isqlsql);
Commit;
endPROC_SUNHONGBO_MONCHNL;
/
Commit;
主要內(nèi)容如下:
1.1異常處理概念
1.1.1預(yù)定義的異常處理
1.1.2非預(yù)定義的異常處理
1.1.3用戶自定義的異常處理
I.1.4用戶定義的異常處理
1.2異常錯誤傳播
1.2.1在執(zhí)行局部引發(fā)異常錯誤
1.2.2在聲明局部引發(fā)異常錯誤
1.3異常錯誤處理編程
1.4在PL/SQL中使用SQLCODE,SQLERRM異常處理函數(shù)
即使是寫得最好的PL/SQL程序也會遇到錯誤或未預(yù)料到的事件。一個優(yōu)秀的程序都應(yīng)該能夠正確處理各種出錯
情況,并盡可能從錯誤中恢復(fù)。任何ORACLE錯誤(報告為ORA-xxxxx形式的Oracle錯誤號)、PL/SQL運行錯
誤或用戶定義條件(不一寫是錯誤),都可以。當(dāng)然了,PL/SQL編譯錯誤不能通過PL/SQL異常處理來處理,因
為這些錯誤發(fā)生在PL/SQL程序執(zhí)行之前。
ORACLE提供異常情況(EXCEPTION)和異常處理(EXCEPTIONHANDLER)來實現(xiàn)錯誤處理。
1.1異常處理概念
異常情況處理(EXCEPTION)是用來處理正常執(zhí)行過程中未預(yù)料的事件,程序塊的異常處理預(yù)定義的錯誤和自定義
錯誤,由于PL/SQL程序塊一旦產(chǎn)生異常而沒有指出如何處理時,程序就會自動終止整個程序運行.
有三種類型的異常錯誤:
1.預(yù)定義(Predefined)錯誤
ORACLE預(yù)定義的異常情況大約有24個。對這種異常情況的處理,無需在程序中定義,由ORACLE自動將其
引發(fā)。
2.非預(yù)定義(Predefined)錯誤
即其他標(biāo)準(zhǔn)的ORACLE錯誤。對這種異常情況的處理,需要用戶在程序中定義,然后由ORACLE自動將其引
發(fā)。
3.用戶定義(Usejdefine)錯誤
程序執(zhí)行過程中,出現(xiàn)編程人員認為的非正常情況。對這種異常情況的處理,需要用戶在程序中定義,然后顯
式地在程序中將其引發(fā)。
異常處理局部一般放在PL/SQL程序體的后半部,結(jié)構(gòu)為:
EXCEPTION
WHENfirstexceptionTHEN<codetohandlefirstexception>
WHENsecond_exceptionTHEN<codetohandlesecondexception>
WHENOTHERSTHEN<codetohandleothersexception>
END;
異常處理可以按任意次序排列,但OTHERS必須放在最后.
1.1.1預(yù)定義的異常處理
預(yù)定義說明的局部ORACLE異常錯誤
錯誤號異常錯誤信息名稱說明
ORA-0001Dup_val_on_index違反了唯一性限制
0RA-0051Timeout-on-resource在等待資源時發(fā)生超時
ORA-0061Transaction-backed-out由于發(fā)生死鎖事務(wù)被揪消
ORA-1001Invalid-CURSOR試圖使用一個無效的海標(biāo)
0RA-1012Not-loggcd-on沒有連接到ORACLE
0RA-1017Login-denied無效的用戶名/口令
ORA-1403NodatafoundSELECTINTO沒有找到數(shù)據(jù)
ORA-1422Too_many_rowsSELECTINTO返回多行
ORA-1476Zero-divide試圖被零除
ORA-1722Invalid-NUMBER轉(zhuǎn)換一個數(shù)字失敗
0RA-6500Storage-error內(nèi)存不夠引發(fā)的內(nèi)部錯誤
ORA-6501Program-error內(nèi)部錯誤
ORA-6502Value-error轉(zhuǎn)換或截斷錯誤
ORA-6504Rowtype-mismatch宿主游標(biāo)變量與PL/SQL變量有不兼容行類型
ORA-6511CURSOR-already-OPEN試圖翻開一個已處于翻開狀態(tài)的游標(biāo)
0RA-6n30Ar.cpRs-TNTO-nnl1試圖為null對象的屬性賦侑
ORA-6531Collcction-is-null試圖將Exists以外的桀合(collection)方法應(yīng)用于一
個nullpl/sql表上或varray上
ORA-6532Subscript-outside-1imit對嵌套或vauay索引得引用超出聲明范圍以外
ORA-6533Subscript-beyond-count對嵌套或varray索引得引用大于集合中元素的個數(shù).
對這種異常情況的處理,只需在PL/SQL塊的異常處理局部,直接引用相應(yīng)的異常情況名,并對其完成相應(yīng)的異
常錯誤處理即可。
例1:更新指定員工工資,如工資小于1500,則加100;
DECLARI:
vempnoemployees,employeeidMYPE:=&empno;
v_salemployees.salary%TYPE;
BEGIN
SELECTsalaryINTOv_salI'ROMemployeesWHEREemployee_id=v_empno;
IFv_sal<-1500THEN
UPDATEemployeesSETsalary=salary+100WHEREemp1oyce_id=v_empno;
DBMS_OUTPUT.PUT_LINE『編碼為'11v_empnoII'員工工資巳更新!');
ELSE
DBMS_OUTPUT.PUT_UNE『編碼為'||v_empno|I'員工工資巳經(jīng)超過規(guī)定值!');
ENDIF;
EXCEPTION
WHENNO_DATA_FOUNDTHEN
DBMS_OUTPUT.PUT_LINE('數(shù)據(jù)庫中沒有編碼為'11v_empno||'的員工');
WHENTOOMANYROWSTHEN
DBMS_OUTPUT.PUT_LINE('程序運行錯誤!請使用游標(biāo)');
WHENOTHERSTHEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'-一'|ISQLERRM);
END;
1.1.2非預(yù)定義的異常處理
對于這類異常情況的處理,首先必須對非定義的ORACLE錯誤進行定義。步驟如下:
1.在PL/SQL塊的定義局部定義異常情況:
<異常情況)EXCEPTION;
2.籽其定義好的異常情況,與標(biāo)準(zhǔn)的ORACLE錯誤聯(lián)系起來,使用EXCEPTIONJNIT語句:
PRAGMAEXCEPTIONINIT《異常情況》,<錯誤代碼》);
3.在PL/SQL塊的異常情況處理局部對異常情況做出相應(yīng)的處理。
例2:刪除指定部門的記錄信息,以確保該部門沒有員工。
INSERTINTOdepartmentsVALUES(50,'FINANCE','CHICAGO');
DECLARE
v_dcptnodepartments,departmentid%TYPE:=Sdcptno;
d?ptno_i'GmainingEXCEPTION;
PRAGMAEXCEPTIONTNIT(deplnoremaining,-2292);
/*-2292是違反一致性約束的錯誤代碼*/
BEGIN
DELETEFROMdepartmentsWHEREdepartment_id=vdeptno;
EXCEPTION
WHENdcptno_rcmainingTHEN
DBMS_OUTPUT.PUT_LINE('違反數(shù)據(jù)完整性約束!');
WHENOTHERSTHEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'--'ISQLERRM);
END:
1.1.3用戶自定義的異常處理
當(dāng)與一個異常錯誤相關(guān)的錯誤出現(xiàn)k,就會隱含觸發(fā)該異常錯誤。用戶定義的異常錯誤是通過顯式使
用RAISE語句來觸發(fā)。當(dāng)引發(fā)一個異常錯誤時,控制就轉(zhuǎn)向到EXCEPTION塊異常錯誤局部,執(zhí)行錯誤處理
代碼。
對于這類異常情況的處理,步驟如下:
1.在PL/SQL塊的定義局部定義異常情況:
<異常情況)EXCEPTION;
2.RAISE<異常情況);
3.在PL/SQL塊的異常情況處理局部對異常情況做出相應(yīng)的處理。
例3:更新指定員工工資,增加100;
DECLARE
v_empnoemployees.employee_id%TYPE:=&empno;
no.resultEXCEPTION;
BEGIN
UPDATEemployeesSETsalary=salary+100WHEREemployee_id=v_empno;
IFSQL%NOTFOUNDTHEN
RAISEno_result;
ENDIF;
EXCEPTION
WHENno_resultTHEN
DBMS_OUTPUT.PUT_L1雁('你的數(shù)據(jù)更新語句失敗了!');
WHENOTHERSTHEN
DRMS.OUTPUT.Pl)T_I.TNF(SQI.CODE|)'——'iISQLERRM):
END;
1.1.4用戶定義的異常處理
調(diào)用DBMSSTANDARD(()RACLE提供的包)包所定義的RAISEAPPLICATIONERROR過程,叮以重新定義異常錯誤消息,
它為應(yīng)用程序提供了一種與ORACLE交互的方法。
RAISE_APPLICATION_ERROR的語法如下:
RAISEAPPLICATIONERROR(errornumber,errormessage,[keeperrors]):
這里的errojnumber是從-20,000到-20,999之間的參數(shù),
errormessage是相應(yīng)的提示信息(<2048字節(jié)),
keep_errors為可選,如果keep_errors=TRUE,則新錯誤將被添加到已經(jīng)引發(fā)的錯誤列表中。如果
keep_errors=FALSE(缺省),則新錯誤將替換當(dāng)前的錯誤列表。
例4:創(chuàng)立一個函數(shù)get_salary,該函數(shù)檢索指定部門的工資總和,其中定義了-20991和-20992號錯誤,分別
處理參數(shù)為空和非法部門代碼兩種錯誤:
CREATETABLEerrlog(
ErrcodeNUMBER,
ErrtextCHAR(40));
CREATEORREPLACEFUNCTIONget_salary(p_deptnoNUMBER)
RETURNNUMBER
AS
v_salNUMBER;
BEGIN
IFp_deptnoISNULLTHEN
RAISEAPPLICATIONERROR(-20991,'部門代碼為空');
ELSIEp_deptno<0THEN
RAISE_APPLTCATION_ERROR(-20992.'無效的部門代碼');
ELSE
SELECTSUM(employees,salary)INTOv_salFROMemployees
WHRREemployees.departmen1_id=p_dcptno:
RETURNv_sal;
ENDTF;
END;
DECLARE
V.salaryNUMBER(7.2);
V_sqlcodeNUMBER;
V_sqlerrVARCHAR2(512);
NulldeptnoEXCEPTION;
Invalid_deptnoEXCEPT!ON;
PRAGMAEXCEPTTON_INTT(nulldeptno,-20991);
PRAGMAEXCEPTION_INIT(invalid_deptno,-20992);
BEGIN
V_salary:=gct_salary(10);
DBMS_OLTPUT.PUT_LINE('1O號部門工資:'TO_CHAR(V_salary));
BEGIN
V_salary:=get_salary(-10);
EXCEPTION
WHENinvalid_deptnoTHEN
V_sqIcodc:=SQLCODE;
V_sqlerr:=SQLERRM;
INSERTINTOcrrlog(crrcodc,errtext)
VALUES(v_sq1code,v_sqlerr);
COMMIT;
ENDinnerl;
V_salary:=get_salary(20);
DBMS_OUTPUT.PUT_LINE('部門號為20的工資為:'【TO_CHAR(V_salary));
BEGIN
V_salary:=get_salary(NULL);
ENDinner2;
V_salary:=get_salary(30);
DBMS_OUTPUT.PUT_LINE('部門號為30的工資為:'|TO_CHAR(V.salary):>;
EXCEPTION
WHENnull_deptnoTHEN
V_sq1code:=SQLCODE;
V_sqlerr:=SQLERRM;
INSERTINTOerrlog(crrcode,errtext)VALUES(vsqlcode,v_sqlcrr);
COMMIT;
WHENOTHERSTHEN
DBMS_OUTPUT.PUT_LINE(SQLCODE|'-'1SQLERRM);
ENDouter:
例5:定義觸發(fā)器,使用RAISE_APPLICATION_ERROR阻止沒有員工姓名的新員式記錄插入:
CREATEORREPLACETRIGGERtr_insert_emp
BEFOREINSERTONemployees
FOREACHROW
BEGIN
IF:new.first_nameISNULLOR:new.last_nameisnullTHEN
RAISEAPPLICATIONERROR(-20000,'Employeemusthaveaname.');
ENDIF;
END.
1.2異常錯誤傳播
由于異常錯誤可以在聲明局部和執(zhí)行局部以及異常錯誤局部出現(xiàn),因而在不同局部引發(fā)的異常錯誤也不
一樣。
1.2.1在執(zhí)行局部引發(fā)異常錯誤
當(dāng)一個異常錯誤在執(zhí)行局部引發(fā)時,有以下情況:
1如果當(dāng)前塊對該異常錯誤設(shè)置了處理,則執(zhí)行它并成功完成該塊的執(zhí)行,然后控制轉(zhuǎn)給包含塊。
1如果沒有對當(dāng)前塊異常錯誤設(shè)置定義處理器,則通過在包含塊中引發(fā)它來傳播異常錯誤。然后對該包含塊執(zhí)
行步驟Do
1.2.2在聲明局部引發(fā)異常錯誤
如果在聲明局部引起異常情況,即在聲明局部出現(xiàn)錯誤,那么該錯誤就能影響到其它的塊。比方在有如
下的PL/SQL程序:
DECLARE
namevarchar2(12):='EricHir:
其它語句
BEGIN
其它語句
EXCEPTION
WHENOTHERSTHEN
其它語句
END;
例子中,由于Abenumber(3)=Jabc';出錯,盡管在EXCEPTION中說明了WHENOTHERSTHEN語
句,但州IENOTHERSTHEN也不會被執(zhí)行。但是如果在該錯誤語句塊的外部有一個異常錯誤,則該錯誤能被
抓住,如:
BEGIN
DECLARE
namevarchar2(12):='EricHur;
其它語句
BEGIN
其它語句
EXCEPTION
WHENOTHERSTHEN
其它語句
END;
EXCEPTION
WHENOTHERSTHEN
其它語句
END;
1.3異常錯誤處理編程
在一般的應(yīng)用處理中,建議程序人員要用異常處理,因為如果程序中不聲明任何異常處埋,則在程序運
行出錯時,程序就被終止,并且也不提示任何信息。下面是使用系統(tǒng)提供的異常來編程的例子。
1.4在PL/SQL中使用SQLCODE,SQLERRM異常處理函數(shù)
由于ORACLE的錯信息最大長度是512字節(jié),為了得到完整的錯誤提示信息,我們可用SQLERRM
和SIJRSTR函數(shù)一起得到錯誤提示信息,方便進行錯誤.特別是如果WHENOTHERS異常處理器時更為方便八
SQLCODE返回遇到的Orac1e錯誤號,
SQLERRM返回遇到的Orac1e錯誤信息.
如:SQI£ODE=-1OO6SQLERRM:'no_data_found'
SQLCODE=OeSQLERRM=*normal,successfualcompletion'
例6.將ORACLE錯誤代碼及其信息存入錯誤代碼表
CREATETAB1.Eerrors(errnumNUMBER(4),errmsgVARCIIAR2(100));
DECLARE
crr.msgVARCHAR2(1OO);
BEGIN
/?得到所有ORACLE錯誤信息?/
FORerr_numIN-100..0LOOP
err_msg:=SQLERRM(err_num);
INSERTINTOerrorsVALUES(err_num,err_msg);
ENDLOOP;
END;
DROPTABLEerrors;
例7.查詢ORACLE錯誤代碼;
BEGIN
INSERTINTOemployees(employee_id,first_name,last_name,hire_date,department_id)
VALUES(2222,'Eric','Hu',SYSDATE,20);
DBMS_OUTPUT.PUT_LINE('插入數(shù)據(jù)記錄成功!');
INSERTINTOemp1oyees(emp1oyeeid,firstname,lastname,hiredate,departmentid)
VALUES(2222,'胡‘,‘勇',SYSDATE,20);
DBMSOUTPUT.PLTJINE('插入數(shù)據(jù)記錄成功!');
EXCEPTION
WHENOTHERSTHEN
DBMS_OUTPUT.PUT_LINE(SQLCODE|I'——'llSQLERRM);
END;
例8.利用ORACLE錯誤代碼,編寫異常錯誤處理代碼;
DFCI.ARE
empno_remainingEXCEPTION;
PRAGMAEXCEPTION_TNIT(empno_remaining,-1);
/*-1是違反唯一約束條件的錯誤代碼*/
BEGIN
INSERTINTOemployees(cinployee_id,first_namc,1ast_name,hire_datc,department_id)
VALUES(3333,'Eric','Hu',SYSDATE,20);
DBMSOUTPUT.PUTLINE('插入數(shù)據(jù)記錄成功!');
INSERTINTOemployees(employee_id,first_name,last_name,hire_date,department_id)
VALUES(3333,'胡','勇',SYSDATE,20);
DBMS_OUTPUT.PUT_LINE('插入數(shù)據(jù)記錄成功!');
EXCEPTION
WHENempno_remainingTHEN
DBMSOUTPUT.PUTLINE('違反數(shù)據(jù)完整性約束!');
WHENOTHERSTHEN
DBMS_OUTPUT.PUT_LINE(SQI.CODE|I'一一'||SQLERRM);
END;
Oracle存儲過程異常處理
1、異常的優(yōu)點
如果沒有異常,在程序中,應(yīng)當(dāng)檢查每個命令的成功還是失敗,如
BEGIN
SELECT...
-checkfor'nodatafound'error
SELECT...
-checkfor'nodatafound'error
SELECT...
--checkfor'noda:afound,error
這種實現(xiàn)的方法缺點在于錯誤處理沒有與正常處理分開,可讀性差,使用異常,可
以方便處理錯誤,而且異常處理程序與正常的事務(wù)邏輯分開,提高了可讀性,如
BEGIN
SELECT...
SELECT
SELECT...
???
EXCEPTION
WHENNODATAFOUNDTHEN--catchesal1'nodatafound'errors
2、異常的分類
有兩種類型的異常,一種為內(nèi)部異常,一種為用戶自定義異常,內(nèi)部異常是執(zhí)行期
間返回到PL/SQL塊的ORACLE錯誤或由PL/SQL代碼的某操作引起的錯誤,如除數(shù)為零
或內(nèi)存溢出的情況。用戶自定義異常由開發(fā)者顯示定義,在PL/SQL塊中傳遞信息以控
制對于應(yīng)用的錯誤處理。
每當(dāng)PL/SQL違背了ORACLE原則或超越了系統(tǒng)依賴的原則就會隱式的產(chǎn)生內(nèi)部異
常。因為每個ORACLE錯誤都有一個號碼并且在PL/SQL中異常通過名字處理,ORACLE
提供了預(yù)定義的內(nèi)部異常。如SELECTINTO語句不返回行時產(chǎn)生的ORACLE異常
NO_DATA_FOUNDo對于預(yù)定義異常,現(xiàn)將最常用的異常列舉如下:
exceptionoracleerrorsqlcodevaluecondition
nodata_foundora-01403+100selectinto
語句沒有符合條件的記錄返回
too_many_rowsora-01422-1422selectinto語句符合條件的記錄有多條
返回
dup_val_on_indexora-00001T對于數(shù)據(jù)庫表中的某一列,該列已經(jīng)被限
制為唯一索引,程序試圖存儲兩個重復(fù)的值
value_errorora-06502-6502在轉(zhuǎn)換字符類型,截取或長度受限時,會發(fā)
生該異常,如一個字符分配給一個變量,而該變量聲明的長度比該字符短,就會引發(fā)該
異常
storage_errorora-06500-6500內(nèi)存溢出
zero_divideora-01476-1476除數(shù)為零
case_not_foundora-06592-6530對于選擇case語句,沒有與之相匹配的
條件,同時,也沒有else語句捕獲其他的條件
cursor_already_openora-06511-6511程序試圖翻開一個已經(jīng)翻開的游
標(biāo)
timeout_on_resourceora-00051-51系統(tǒng)在等待某一資源,時間超時
如果要處理未命名的內(nèi)部異常,必須使用OTHERS異常處理器或PRAGMA
EXCEPTION_INIT。PRAGMA曰編譯器控制,或者是對于編譯器的注釋。PRAGMA在編譯時
處理,而不是在運行時處理。EXCEPTIONINIT告訴編譯器將異常名與ORACLE錯誤碼結(jié)
合起來,這樣可以通過名字引用任意的內(nèi)部異常,并且可以通過名字為異常編寫一適當(dāng)
的異常處理器。
在子程序中使用EXCEPTIONINIT的語法如下:
PRAGMAEXCEPTIONTNIT(exceptionname,-Oracleerror_number);
在該語法中,異常名是聲明的異常,下例是其用法:
DECLARE
deadlock_dctcctedEXCEPTION;
PRAGMAEXCEPTION_INIT(deadlock_detected,-60);
BEGIN
…一一Someoperationthatcausesan0RA-00060error
EXCEPTION
WHENdeadlockdetectedTHEN
一handletheerror
END;
對于用戶自定義異常,只能在PL/SQL塊中的聲明局部聲明異常,異常的名字由
EXCEPTION關(guān)鍵字引入:
reservedloanedException
產(chǎn)生異常后,控制傳給了子程序的異常局部,將異常轉(zhuǎn)向各自異??刂茐K,必須在
代碼中使用如下的結(jié)構(gòu)處理錯誤:
Exception
Whenexceptionlthen
Sequenceofstatements;
Whenexception?then
Sequenceofstatements;
Whenothersthen
3、異常的拋出
由三種方式拋出異常
1.通過PL/SQL運行射引擎
2.使用RAISE語句
3.調(diào)用RAISE_APPLICATION_ERROR存儲過程
當(dāng)數(shù)據(jù)庫或PL/SQL在運行時發(fā)生錯誤時,一個異常被PL/SQL運行時引擎自動拋出。
異常也可以通過RAISE語句拋出
RAISEexceptionname;
顯式拋出異常是程序員處理聲明的異常的習(xí)慣用法,但RAISE不限于聲明了的異常,
它可以拋出任何任何異常。例如,你希望用TIMEOUTONRESOURCE錯誤檢測新的運行時
異常處理器,你只需簡單的在程序中使用下面的語句:
RAISETIMEOUTON_RESOUCE;
比方下面一個訂單輸入的例子,若當(dāng)訂單小于庫存數(shù)量,則拋出異常,并且捕獲該
異常,處理異常
DECLARE
inventory_too_lowEXCEPTION;
--其他聲明語句
BEGIN
IForderrec.qty>inventoryrec.qtyTHEN
RAISEinventorytoolow;
ENDIF
EXCEPTION
WHENinventory_too_lowTHEN
order_rec.staus:=rbackordered1;
END;
RAISE_APPLICATION_ERROR內(nèi)建函數(shù)用于拋出一個異常并給異常賦予一個錯誤號以
及錯誤信息。自定義異常的缺省錯誤號是+1,缺省信息是UserJ)efined_Exception0
RAISE.APPLICATION_ERROR函數(shù)能夠在pl/sql程序塊的執(zhí)行局部和異常局部調(diào)用,顯式
拋出帶特殊錯誤號的命名異常。
Raiseapplicationerror(errornumber,message[,true,false]))
錯誤號的范圍是-20,000到-20,999。錯誤信息是文本字符串,最多為2048字節(jié)。
TRUE和FALSE表示是添加(TRUE)進錯誤堆(ERRORSTACK)還是覆蓋(overwrite)錯誤堆
(FALSE)o缺省情況下是FALSE。
如下代碼所示:
IFproduct_not_foundTHEN
RAISE_APPLICATION_ERROR(-20123,1Invaldproductcode1TRUE);
ENDIF;
4、異常的處理
PL/SQL程序塊的異常局部包含了程序處理錯誤的代碼,當(dāng)異常被拋出時,一個異常
陷阱就自動發(fā)生,程序控制離開執(zhí)行局部轉(zhuǎn)入異常局部,一旦程序進入異常局部就不能
再回到同一塊的執(zhí)行局部。下面是異常局部的一般語法:
EXCEPTION
WHENexception_nameTHEN
Codeforhandingexceptionname
[WHENanotherexceptionTHEN
CodeforhandinganoLher_exception]
[WHENothersTHEN
codeforhandinganyotherexception.]
用戶必須在獨立的WHEN子串中為每個異常設(shè)計異常處理代碼,WHENOTHERS子串必
須放置在最后面作為缺省處理器處理沒有顯式處理的異常。當(dāng)異常發(fā)生時,控制轉(zhuǎn)到異
常局部,ORACLE查找當(dāng)前異常相應(yīng)的WHEN..THEN語句,捕捉異常,THEN之后的代碼被
執(zhí)行,如果錯誤陷阱代碼只是退出相應(yīng)的嵌套塊,那么程序?qū)⒗^續(xù)執(zhí)行內(nèi)部塊END后面
的語句。如果沒有找到相應(yīng)的異常陷阱,那么將執(zhí)行WHENOTHERS。在異常局部WHEN子
串沒有數(shù)量限制。
EXCEPTION
WHENinventory_too_lowTHEN
ordcr_rcc.staus:-*backorderedr;
replenish_inventory(inventorynbr=>
inventoryrec.sku,minamount二〉orderrec.qty-inventoryrec.qty);
WHENdiscontinueditemTHEN
一一codefordiscontinued_itemprocessing
WHENzero_divideTHEN
一codeforzero_divide
WHENOTHERSTHEN
-codeforanyotherexception
END;
當(dāng)異常拋出后,控制無條件轉(zhuǎn)到異常局部,這就意味著控制不能回到異常發(fā)生的位
置,當(dāng)異常被處理和解決后,控制返回到上一層執(zhí)行局部的下一條語句。
BEGIN
DECLARE
bad_creditexception:
BEGIN
RAISEbadcredit;
一發(fā)生異常,控制轉(zhuǎn)向;
EXCEPTION
WHENbad_creditTHEN
dbms_output.put_line(1bad_credit1);
END;
一bad_crcdit異常處理后,控制轉(zhuǎn)到這里
EXCEPTION
WHENOTHERSTHEN
--控制不會從bad_credit異常轉(zhuǎn)到這里
一因為bad_credit已被處理
END;
當(dāng)異常發(fā)生時,在塊的內(nèi)部沒有該異常處理器時,控制將轉(zhuǎn)到或傳播到上一層塊的
異常處理局部。
BEGIN
DECLARE-—內(nèi)部塊開始
bad_creditexception:
BEGIN
RAISEbadcredit;
一發(fā)生異常,控制轉(zhuǎn)向:
EXCEPTION
WHENZERO_DIVIDETHEN一不能處理bad_credite異常
dbms_output.put_linc(1dividebyzeroerror*);
END一結(jié)束內(nèi)部塊
一控制不能到達這里,因為異常沒有解決;
一異常局部
EXCEPTION
WHENOTHERSTHEN
一由于bad_credit沒有解決,控制將轉(zhuǎn)到這里
END;
5、異常的傳播
沒有處理的異常將沿檢測異常調(diào)用程序傳播到外面,當(dāng)異常被處理并解決或到達程
序最外層傳播停止。在聲明局部拋出的異常將控制轉(zhuǎn)到上一層的異常局部。
BEGIN
executablestatements
BEGIN
todayDATE:='SYADATE';—ERRROR
BEGIN一內(nèi)部塊開始
dbms_output.put_line(rthislinewillnotexecute1);
EXCEPTION
WHENOTHERSTHEN
一異常不會在這里處理
END;—內(nèi)部塊結(jié)束
EXCEPTION
WHENOTHERSTHEN
處理異常
END
處理oracle系統(tǒng)自動生成系統(tǒng)異常外,可以使用raise來手動生成錯誤。
1Raiseexception;
1Raisepackage,exception;
1Raise:
以上是raise的三種使用方法。第一種用于生成當(dāng)前程序中定義的異?;?/p>
在standard中的系統(tǒng)異常。
Declare
Invalid_idexception;
Id_valuesvarchar(2);
Begin
Id_value:=id_for('smith');
Ifsubstr(id_value,1,1)!=,x'
Then
Raiseinvalid_id;
Endif;
Exception
Wheninvalid_id
Then
Dbir.soutput,putline('thisisan
invalidid!’);
End;
這是一個生成自定義異常的例子,當(dāng)然也可以生成系統(tǒng)異常:
declare
cmployee__idinnumber;
Begin
Selectemployee_idintoeir.ployee_id_infromemploy_listwhereemp1oyee_name=&n;
Ifemployee_id_in=0
Then
Raisezerodevided;
Endif;
Exception
Whenzero_devided
Then
Dbir.s_output.put_line('wrong!’);
End;
有一些異常是定義在非標(biāo)準(zhǔn)包中的,如UTL_FILE,DBMS_SQL以及程序員創(chuàng)立的
包中異常??梢允褂胷aise的第二種用法來生成異常。
Ifday_overdue(isbn_in,browser_in)>365
Then
Raiseoverdue_pkg.book_is_lost
Endif;
在最后一種raise的形式中,不帶任何參數(shù)。這種情況只出現(xiàn)在希望將當(dāng)前的異常
傳到外部程序時。
Exception
Whennodatafound
Then
Raise;
End;
Pl.sql使用raise_app1ication_error過程來生成一個有具體描述的異常。當(dāng)使
用這個過程時,當(dāng)前程序被中止,輸入輸出參數(shù)被置為原先的值,但任何DML對數(shù)
據(jù)庫所做的改動將被保存,可以在之后用rollback命令回滾。下面是該過程的原型:
Procedureraiseapplicationerror(
Numbinary.integer;
Msgvarchar2;
Keeperrors:ackBooleandefaultfalse
)
其中num是在-20999到-20000之間的任何數(shù)字(但事實
上,DBMS_OUPUT和DBMS_DESCRIBLE包使用了-20005到-20000的數(shù)
字);msg是小于2K個字符的描述語,任何大于2K的字符都將被自動丟
棄;keeperrorstack默認為false,是指清空異常棧,再將當(dāng)前異常人棧,如
果指定true的話就直接將當(dāng)前異常壓入棧中。
CREATEORREPLACEPROCEDUREraise_by_language(code.inINPLS_INTEGER)
IS
1messageerrortable,errorstrin喻TYPE;
BEGIN
SELECTerror_string
INTO1message
FROMerrortable,v$nls_parametersv
WHEREerror_number=code_in
ANDstring_language=v.VALUE
ANDv.parameter=rNLS_LANGUAGEr;
RAISE_APPLICATION_ERROR(codc_in,l_mcssagc);
END;
ORACL內(nèi)部異常:
ORA-OOOOl:違反唯一約束條件(.)
ORA-00017:請求會話以設(shè)置跟蹤事件
ORA-0D018:超出最大會話數(shù)
ORA-00019:超出最大會話許可數(shù)
ORA-00020:超出最大進程數(shù)()
ORA-00021:會話附屬于其它某些進程;無法轉(zhuǎn)換會話
OR/X-00022:無效的會話1D;訪問被拒絕
ORA-00023:會話引用進程私用內(nèi)存;無法別離會話
ORA-00024:單一進程模式下不允許從多個進程注冊
ORA-00025:無法分配
ORA-00026:喪失或無效的會話ID
ORA-00027:無法刪去當(dāng)前會話
ORA-00028:您的會話己被刪去
ORA-00029:會話不是用戶會話
ORA-00030:用戶會話ID不存在。
ORA-00031:標(biāo)記要刪去的會話
ORA-00032:無效的會話移植口令
ORA-00033:當(dāng)前的會話具有空的移植口令
ORA-00034:無法在當(dāng)前PL/SQL會話中
ORA-00035:LICENSE_MAX_USERS不能小于當(dāng)前用戶數(shù)
ORA-00036:超過遞歸SQL()級的最大值
ORA-00037:無法轉(zhuǎn)換到屬于不同效勞器組的會話
ORA-00038:無法創(chuàng)立會話:效勞器組屬「其它用戶
ORA-00050:獲取入隊時操作系統(tǒng)出錯
ORA-00051:等待資源超時
ORA-00052:超出最大入隊資源數(shù)。
ORA-00053:超出最大入隊數(shù)
ORA-00054:資源正忙,要求指定N0WAIT
ORA-00055:超出DML鎖的最大數(shù)
ORA-00056;對象上的DDL鎖以不兼容模式掛起
ORA-00057:超出臨時表鎖的最大數(shù)
ORA-00058:DB_BLOCK_SIZE必須為才可安裝此數(shù)據(jù)庫(非)
ORA-00059:超出DBFILES的最大值
ORA-00060:等待資源時檢測到死鎖
ORA-00061:另一個例程設(shè)置了不同的DML_LOCKS
(JRA-00062:無法獲得DML全表鎖定;DML_LOCKS為0
ORA-00063:超出LOGFILES的最尤數(shù)
ORA-00064:對象過大以至無法分配在此0/S(,)
ORA-00065:FIXED_DATE的初始化失敗
ORA-00066:LOG_FILES為但需要成為才可兼容
ORA-00067:值對參數(shù)無效;至少必須為
ORA-00068:值對參數(shù)無效,必須在和之間
ORA-00069:無法獲得鎖定--禁用了表鎖定
(JRA-00070:命令無效
ORA-00071:進程號必須介于1和之間
ORA-00072:進程"”不活動
ORA-00073:命令介于和個參數(shù)之間時使用
ORA-00074:未指定進程
()R/\-00075:在此例程未找到進程
ORA-ODO76:未找到轉(zhuǎn)儲
ORA-00077:轉(zhuǎn)儲無效
ORA-00078:無法按名稱轉(zhuǎn)儲變量
ORA-00079:未找到變量
ORA-00080:層次指定的全局區(qū)域無效
ORA-00081:地址范圍[,)不可讀
ORA-00082:的內(nèi)存大小不在有效集合[1],[2],[4]之內(nèi)
ORA-00083:警告:可能損壞映射的SGA
ORA-00084:全局區(qū)域必須為PGA,SGA或UGA
ORA-00085:當(dāng)前調(diào)用不存在
ORA-00086:用戶調(diào)用不存在
ORA-00087:命令無法在遠程例程上執(zhí)行
ORA-00088:共享效勞器無法執(zhí)行命令
ORA-00089:ORADEBUG命令中無效的例程號
()RA-0()090:未能將內(nèi)存分配給群集數(shù)據(jù)庫ORADEBUG命令
ORA-00091:LARGEPOOLSIZE至少必須為
ORA-00092:LARGE_POOL_SIZE必須大于LARGE_POOL_MIN_ALLOC
ORA-00093;必須介于和之訶
ORA-00094:要求整數(shù)值
ORA-00096:值對參數(shù)無效,它必須來自之間
ORA-00097:使用OracleSQL特性不在SQL92級中
ORA-00099:等待資源時發(fā)生超時,可能是PDML死鎖所致
ORA-OOIOO:未找到數(shù)據(jù)
ORA-OOIOI:系統(tǒng)參數(shù)DISPATCHERS的說明無效
ORA-00102:調(diào)度程序無法使用網(wǎng)絡(luò)協(xié)議
ORA-00103:無效的網(wǎng)絡(luò)協(xié)議;供調(diào)度程序備用
ORA-00104:檢測到死鎖;全部公用效勞器已鎖定等待資源
ORA-00105:未配置網(wǎng)絡(luò)協(xié)議的調(diào)度機制
ORA-00106:無法在連接到調(diào)度程序時啟動/關(guān)閉數(shù)據(jù)庫
ORA-00107:無法連接到ORACLE監(jiān)聽器進程
ORA-00108:無法設(shè)置調(diào)度程序以同步進行連接
ORA-OOlll:由于效勞器數(shù)目限制在,所以沒有啟動所有效勞器
ORA-00112:僅能創(chuàng)立多達(最多指定)個調(diào)度程序
ORA-00113:協(xié)議名過長
ORA-00114:缺少系統(tǒng)參數(shù)SERVICE_NAMES的值
ORA-00115:連接被拒絕;調(diào)度程序連接表已滿
ORA-OOH6:SERVICE_NAMES名過長
ORA-OOH7:系統(tǒng)參數(shù)SERVICE_NAMES的值超出范圍
ORA-00118:系統(tǒng)參數(shù)DISPATCHERS的值超出范圍
ORA-00119:系統(tǒng)參數(shù)的說明無效
ORA-00120:未啟用或安裝調(diào)度機制
ORA-00121:在缺少DISPATCHERS的情況下指定了SHARED_SERVERS
ORA-00122:無法初始化網(wǎng)絡(luò)配置
ORA-00123:空閑公用效勞器終止
ORA-00124:在缺少MAX_SHARED_SERVERS的情況下指定了DISPATCHERS
ORA-00125:連接被拒絕;無效的演示文稿
ORA-00126:連接被拒絕;無效的重復(fù)
ORA-00127:調(diào)度進程不存在
ORA-00128:此命令需要調(diào)度進程名
ORA-00129:監(jiān)聽程序地址驗證失敗
ORA-00130:監(jiān)聽程序地址''無效
ORA-00131:網(wǎng)絡(luò)協(xié)議不支持注冊"
ORA-00132:語法錯誤或無法解析的網(wǎng)絡(luò)名稱
ORA-00150:重復(fù)的事務(wù)處理ID
ORA-00151;無效的事務(wù)處理ID
ORA-00152:當(dāng)前會話與請求的會話不匹配
ORA-00153:XA庫中的內(nèi)部錯誤
ORA-00154:事務(wù)處理監(jiān)視器中的協(xié)議錯誤
ORA-00155:無法在全局事務(wù)處理之外執(zhí)行工作
ORA-00160:全局事務(wù)處理長度越出了最大值0
ORA-00161:事務(wù)處理的分支長度非法(允許的最大長度為)
ORA-00162:外部dbid的長度越出了最大值()
ORA-00163:內(nèi)部數(shù)據(jù)庫名長度越出了最大值()
ORA-00164:在分布式事務(wù)處理中不允許獨立的事務(wù)處理
0RA-0D165:不允許對遠程操作進行可移植分布式自治轉(zhuǎn)換
ORA-00200:無法創(chuàng)立控制文件
ORA-00201:控制文件版本與ORACLE版本不兼容
ORA-00202:控制文件:一
OR/X-00203:使用錯誤的控制文件
ORA-00204:讀控制文件時出錯(塊,#塊)
ORA-00205:標(biāo)識控制文件出錯,有關(guān)詳情,請檢查警告日志
ORA-00206:寫控制文件時出錯(塊,#塊)
ORA-00207:控制文件不能用于同一數(shù)據(jù)庫
ORA-00208:控制文件的名稱數(shù)超出限制
ORA-00209:控制文件塊大小不匹配,有關(guān)詳情,請檢查警告日志
ORA-00210:無法翻開指定的控制文件
ORA-00211:控制文件與先前的控制文件不匹配
ORA-00212:塊大小低于要求的最小大?。ㄗ止?jié))
ORA-00213:不能重新使用控制文件;原文件大小為,還需
ORA-00214:控制文件''版本與文件‘‘版本不一致
ORA-00215:必須至少存在一個控制文件
ORA-00216:無法重新調(diào)整從8.0.2移植的控制文件大小
ORA-00217:從9.0.1進行移植無法重新調(diào)整控制文件的大小
ORA-00218:控制文件的塊大小與DB_BLOCK_SIZE0不匹配
ORA-00219:要求的控制文件大小超出了允許的最大值
ORA-00220:第一個例程未安裝控制文件,有關(guān)詳情,請檢查警告日志
ORA-00221:寫入控制文件出錯
ORA-00222:操作將重新使用當(dāng)前已安裝控制文件的名稱
0RA-0D223:轉(zhuǎn)換文件無效或版本不正確
ORA-00224:控制文件重設(shè)大小嘗試使用非法記錄類型()
ORA-00225:控制文件的預(yù)期大小與實際大小不同
ORA-00226:咯用控制文件翻開時不允許進行操作
ORA-00227:控制文件中檢測到損壞的塊:(塊,#塊)
ORA-00228:備用控制文件名長度超出了最大長度
ORA-00229:操作不允許:已掛起快照控制文件入隊
ORA-00230:操作不允許:無法使用快照控制文件入隊
ORA-00231:快照控制文件未命名
ORA-00232:快照控制文件不存在,已損壞或無法讀取
ORA-00233:控制文件副木已損壞或無法讀取
ORA-00234:標(biāo)識或翻開快照或復(fù)制控制文件時出錯
ORA-00235:控制文件固定表因并發(fā)更新而不一致
ORA-00236:快照操作不允許:掛上的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 撞護欄賠償協(xié)議書
- 長期購銷合同協(xié)議
- 錘鏨工分包協(xié)議書
- 門衛(wèi)室安全協(xié)議書
- 招生協(xié)議合同范本
- 限合伙投資協(xié)議書
- 陌陌播主協(xié)議合同
- 銀行卡商戶協(xié)議書
- 收購香港保協(xié)議書
- 銷售合同附屬協(xié)議
- 學(xué)堂在線雨課堂《唐宋名家詞(河南大學(xué))》網(wǎng)課學(xué)堂云單元測試考核答案
- 煤礦班組長安全培訓(xùn)
- 體育培訓(xùn)校區(qū)管理制度
- 住宅項目工程總承包管理策劃(可編輯)
- 小學(xué)消防安全工作責(zé)任體系
- 2025廣西桂林市面向全國高校招聘急需緊缺專業(yè)人才147人筆試備考試卷及答案解析(奪冠)
- 家具擺放施工方案
- 樓體亮化維修合同
- 2025年河南省人民法院聘用書記員考試試題及答案
- 二類洞充填課件
- 腎病的危害與防治科普
評論
0/150
提交評論