📄 第七章 控制pl-sql错误 - pl-sql用户指南与参考 - whatiswhat.htm
字号:
href="http://blog.chinaunix.net/u1/44734/index.html">首页</A> </LI></UL></TD>
<TD width=10></TD></TR>
<TR>
<TD colSpan=4>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0
cellPadding=0 width=980 border=0>
<TBODY>
<TR>
<TD></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<SCRIPT language=javascript>function $(s){return document.getElementById(s);}function ShowHideDiv(divid,iImg){if($(divid).style.display == "none"){iImg.src="../../templates/newgreen/images/dot2.gif";$(divid).style.display = "block";iImg.title="收起";}else{iImg.src="../../templates/newgreen/images/dot4.gif";$(divid).style.display = "none";iImg.title="展开";}}navHover();</SCRIPT>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0
cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD height=3></TD></TR></TBODY></TABLE><BR>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0
cellPadding=0 width="90%" align=center border=0>
<TBODY>
<TR>
<TD width=18 height=28><IMG alt=""
src="第七章 控制PL-SQL错误 - PL-SQL用户指南与参考 - whatiswhat.files/bg_art_left_top.gif"
border=0></TD>
<TD
background="第七章 控制PL-SQL错误 - PL-SQL用户指南与参考 - whatiswhat.files/bg_art_top.gif">
<P style="MARGIN: 5px; LINE-HEIGHT: 150%"></P></TD>
<TD width=18 height=28><IMG alt=""
src="第七章 控制PL-SQL错误 - PL-SQL用户指南与参考 - whatiswhat.files/bg_art_right_top.gif"
border=0></TD></TR>
<TR>
<TD width=18
background="第七章 控制PL-SQL错误 - PL-SQL用户指南与参考 - whatiswhat.files/bg_art_left.gif"></TD>
<TD align=middle bgColor=#f5fdee><BR><FONT style="FONT-SIZE: 14pt"
color=#295200><B>第七章 控制PL/SQL错误</B></FONT>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#a5bd6b cellSpacing=1
cellPadding=0 width="100%" border=1>
<TBODY>
<TR>
<TD align=middle>
<TABLE style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word"
cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD align=middle>
<TABLE
style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word"
cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD>
<DIV id=art style="MARGIN: 15px">
<DIV class=postTitle><A class=postTitle2
id=AjaxHolder_ctl01_TitleUrl
href="http://www.cnblogs.com/cxd4321/archive/2008/03/19/1113203.html">第七章
控制PL/SQL错误 </A></DIV>
<P class=title1>一、错误控制一览</P>
<P>在PL/SQL中,警告或错误被称为异常。异常可以是内部(运行时系统)定义的或是用户定义的。内部定义的案例包括除零操作和内存溢出等。一些常见的内部异常都有一个预定义的名字,如ZERO_DIVIDE和STORAGE_ERROR等。对于其它的内部异常,我们可以手动为它们命名。
</P>
<P>我们可以在PL/SQL块、子程序或包的声明部分自定义异常。例如,我们可以定义一个名为insufficient_funds的异常来标示帐户透支的情况。与内部异常不同的是,用户自定义异常必须有一个名字。
</P>
<P>错误发生时,异常就会被抛出。也就是说,正常的执行语句会被终止,控制权被转到PL/SQL块的异常控制部分或子程序的异常控制部分。内部异常会由运行时系统隐式地抛出,而用户定义异常必须显式地用RAISE语句抛出,RAISE语句也可以抛出预定义异常。
</P>
<P>为了控制被抛出的异常,我们需要单独编写被称为"exception
handler"的异常控制程序。异常控制程序运行后,当前块就会停止执行,封闭块继续执行下一条语句。如果没有封闭块,控制权会直接交给主环境。
</P>
<P>下例中,我们为一家股票代码(Ticker
Symbol)为XYZ的公司计算并保存市盈率(price-to-earning)。如果公司的收入为零,预定义异常ZERO_DIVIDE就会被抛出。这将导致正常的执行被终止,控制权被交给异常控制程序。可选的OTHERS处理器可以捕获所有的未命名异常。
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>DECLARE</STRONG><BR> pe_ratio <STRONG>NUMBER</STRONG> (3, 1);<BR><STRONG>BEGIN</STRONG><BR> <STRONG>SELECT</STRONG> price / earnings<BR> <STRONG>INTO</STRONG> pe_ratio<BR> <STRONG>FROM</STRONG> stocks<BR> <STRONG>WHERE</STRONG> symbol = <EM>'XYZ'</EM>; <EM>-- might cause division-by-zero error</EM><BR> <STRONG>INSERT</STRONG> <STRONG>INTO</STRONG> stats (symbol, ratio)<BR> <STRONG>VALUES</STRONG> (<EM>'XYZ'</EM>, pe_ratio);<BR> <STRONG>COMMIT</STRONG>;<BR><STRONG>EXCEPTION</STRONG> <EM>-- exception handlers begin</EM><BR> <STRONG>WHEN</STRONG> ZERO_DIVIDE <STRONG>THEN</STRONG> <EM>-- handles 'division by zero' error</EM><BR> <STRONG>INSERT</STRONG> <STRONG>INTO</STRONG> stats (symbol, ratio)<BR> <STRONG>VALUES</STRONG> (<EM>'XYZ'</EM>, <STRONG>NULL</STRONG>);<BR> <STRONG>COMMIT</STRONG>;<BR> ...<BR> <STRONG>WHEN</STRONG> <STRONG>OTHERS</STRONG> <STRONG>THEN</STRONG> <EM>-- handles all other errors</EM><BR> <STRONG>ROLLBACK</STRONG>;<BR><STRONG>END</STRONG>; <EM>-- exception handlers and block end here</EM>
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>上面的例子演示了异常控制,但对于INSERT语句的使用就有些低效了。使用下面的语句就要好一些: </P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>INSERT</STRONG> <STRONG>INTO</STRONG> stats (symbol, ratio)<BR> <STRONG>SELECT</STRONG> symbol, DECODE (earnings, 0, <STRONG>NULL</STRONG>, price / earnings)<BR> <STRONG>FROM</STRONG> stocks<BR> <STRONG>WHERE</STRONG> symbol = <EM>'XYZ'</EM>;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>在下面这个例子中,子查询为INSERT语句提供了数据。如果earnings是零的话,函数DECODE就会返回空,否则DECODE就会返回price与earnings的比值。
</P>
<P class=title1>二、异常的优点</P>
<P>使用异常来控制错误有几个优点。如果没有异常控制的话,每次执行一条语句,我们都必须进行错误检查: </P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>BEGIN</STRONG><BR> <STRONG>SELECT</STRONG> ...<BR> <EM>-- check for ’no data found’ error</EM><BR> <STRONG>SELECT</STRONG> ...<BR> <EM>-- check for ’no data found’ error</EM><BR> <STRONG>SELECT</STRONG> ...<BR> <EM>-- check for ’no data found’ error</EM>
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>错误处理和正常的处理内容界限不明显,导致代码混乱。如果我们不编写错误检查代码,一个错误就可能引起其它错误,有时还可能是一些无关错误。
</P>
<P>但有了异常后,我们就能很方便的控制错误,而且不需要编写多个检查代码: </P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>BEGIN</STRONG><BR> <STRONG>SELECT</STRONG> ...<BR> <STRONG>SELECT</STRONG> ...<BR> <STRONG>SELECT</STRONG> ...<BR> ...<BR><STRONG>EXCEPTION</STRONG><BR> <STRONG>WHEN</STRONG> NO_DATA_FOUND <STRONG>THEN</STRONG> <EM>-- catches all 'no data found' errors</EM>
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>异常能把错误控制程序单独分离出来,改善可读性,主要的算法不会受到错误恢复算法影响。异常还可以提高可靠性。我们不需要在每一个可能出现错误的地方编写错误检查代码了,只要在PL/SQL块中添加一个异常控制代码即可。这样,如果有异常被抛出,我们就可以确保它能够被捕获并处理。
</P>
<P class=title1>三、预定义PL/SQL异常</P>
<P>当我们的PL/SQL程序与Oracle规则相冲突或超过系统相关(system-dependent)的限制时,内部异常就会被抛出。每个
Oracle错误都有一个错误编号,但异常只能按名称捕获,然后被处理。所以,PL/SQL把一些常见Oracle错误定义为异常。例如,如果
SELECT INTO语句查询不到数据时,PL/SQL就会抛出预定义异常NO_DATA_FOUND。 </P>
<P>要控制其它Oracle异常,我们可以使用OTHERS处理器。函数SQLCODE和SQLERRM在OTHERS处理器中特别有用,因为它们能返回Oracle错误编号和消息。另外,我们还可以使用编译指示(pragma)EXCEPTION_INIT把一个异常名称和一个Oracle错误编号关联起来。PL/SQL在STANDARD包中声明了全局预定义异常。所以,我们不需要自己声明它们。我们可以为下面列表中命名的预定义异常编写处理程序:
</P>
<TABLE id=table-list>
<TBODY>
<TR>
<TH id=table-list-head>异常</TH>
<TH id=table-list-head>Oracle错误号</TH>
<TH id=table-list-head>SQLCODE值</TH></TR>
<TR>
<TD>ACCESS_INTO_NULL</TD>
<TD>ORA-06530</TD>
<TD>-6530</TD></TR>
<TR>
<TD>CASE_NOT_FOUND</TD>
<TD>ORA-06592</TD>
<TD>-6592</TD></TR>
<TR>
<TD>COLLECTION_IS_NULL</TD>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -