异常分为预定义异常和用户自定义异常。
预定义异常是由系统定义的异常。由于它们已在standard包中预定义了,因此,这些异常可以直接在程序中使用,而不必在定义部分声明。
用户自定义异常则需要在定义部分声明后才能在可执行部分使用。用户自定义异常对应的错误不一定是oracle异常,例如,它可能是一个数据错误。
1、预定义异常
常见的预定义异常...
--下面的块中产生一个NO_DATA_FOUND异常:















2、异常的声明




声明这样的异常需要使用exception_init编译指令。
例如,在块定义部分声明了一个与错误"ORA-01401:inserted value too large for column"对应的用户自定义异常e_toolarge。当在块的可执行部分向表中插入的列值超出指定的列长度时,则产生e_toolarge异常:




3、异常的产生
当与预定义异常相应的错误出现时,则该预定义异常就会自动产生。而一个用户自定义异常通常由RAISE语句来产生(由exception_init编译指令声明的用户自定义异常也可通过对应oracle错误的出现而产生)。
例1,在下面块中使用raise语句产生用户自定义异常e_toosmallsalary:











例2,预定义异常通常是在与之相对应的错误发生时产生。下面的块产生no_data_found异常。





例3,由exception_init编译指令声明的用户自定义异常与一个oracle错误相连,所以这样的用户自定义异常也是在一个oracle错误发生时产生。
上节中已声明了一个用户自定义异常e_toolarge(使用exception_init编译指令声明)。当向表中插入一个列值超出了该列指定的长度时,会自动产生该异常:




由于输入的作家代码值'A000001'超出了列的长度,所以产生错误"ORA-01401:inserted value too large for column",它对应用户自定义异常toolarge,同时控制权转到块外的调用环境。
通常用户自定义异常是在声明后才能产生,但如果我们使用raise_application_error函数就可以直接产生异常,并且能为异常定义用户自己指定的错误消息。执行完raise_application_error函数后,控制权转到块外的调用情境。
raise_application_error(error_number,error_message[,keep_errors]);
其中,error_number是一个错误号,值在-20000到-20999之间,error_message是与该错误相连的错误消息文本,最大不超过512个字符。keep_errors是一个boolean值。是可选参数,如果为true,则这个新的错误将加在已产生的错误列表之后,如果为false,则这个新错误将代替当前的错误列表。
如:
raise_application_error(-20001,'没有代码为'||p_author_code||'的作家存在');
4、异常处理
异常处理部分包含着对异常的处理语句。当一个异常相应的错误发生导致这个异常发生时,异常处理语句被执行。













如果块中的异常没有被处理,则该块会带着未处理的异常返回调用它的程序,这会导致调用它的程序出错。如果在存储过程中出现异常,则存储过程的OUT参数将得不到返回值。
为了避免未处理异常带来的问题,我们最好在块的最外层使用others子句处理块中所有未处理的异常。这样就能确保所有的错误都能被发现和处理。
(1)处理可执行部分产生的异常
(2)处理定义部分产生的异常
如果是定义部分的一个赋值语句产生了异常,即使在当前块的异常处理部分有处理该异常的处理语句时,也不去执行,而是立刻被传递到外部块中。由外部块处理。
(3)处理异常处理部分产生的异常
在异常处理语句中也可以产生异常,这个异常可以通过raise语句产生,或是由于出现一个运行错误而产生。这两种情况下产生的异常都被立刻传递到块外。
(4)sqlcode和sqlerrm函数
由于others子句处理when子句没有处理的异常,所以在others子句中处理的异常是未知的。我们可以用sqlcode和sqlerrm函数来确定异常对应的错误代码和信息。
异常种类 sqlcode sqlerrm
oracle错误对应的异常 负数 oracle错误
no_data_found +100 no data found
用户自定义异常 +1 user-defined exception
没有产生异常 0 ora-0000:normal,successful completion
注意,如果使用exception_init预编译指令声明与oracle错误相连的自定义异常,则sqlcode和sqlerrm返回对应的oracle错误代码和相应的错误信息,则不是返回"+1"和"user-defined exception"。
例如,下面是一个带有完整的others异常处理语句的PL/SQL块:



















