一、什么是异常?
在执行破坏程序正常运行的程序期间发现错误时会发生异常。
有很多可能的例外原因:用户在输入时出现拼写错误; 程序无法正常工作; 广告网页不存在; 等等。
你能想到在使用网站或应用程序时遇到的错误吗?
二、PL / SQL中的异常
这个例子工作正常。 但是如果你进入“韩国,南方”而不是“韩国”呢?
DECLAREv_country_name wf_countries.country_name%TYPE:= 'Republic of Korea';v_elevation wf_countries.highest_elevation%TYPE;
BEGINSELECT highest_elevationINTO v_elevationFROM wf_countriesWHERE country_name = v_country_name;DBMS_OUTPUT.PUT_LINE(v_country_name);
END;
Republic of Korea
Statement processed.
Exceptions in PL/SQL (continued)
Handling Exceptions
DECLAREv_country_name wf_countries.country_name%TYPE:='Korea, South';v_elevation wf_countries.highest_elevation%TYPE;
BEGINSELECT highest_elevationINTO v_elevationFROM wf_countriesWHERE country_name = v_country_name;
END;
请注意代码无法按预期工作。 没有找到韩国,南韩的数据,因为国名实际上是作为韩国存储的。
PL / SQL中的这种类型的错误称为异常。当代码无法按预期工作时,PL / SQL会引发异常。 发生异常时,您说异常已被“引发”。
三、什么是异常处理程序?
异常处理程序是定义引发异常(即发生错误时)要执行的恢复操作的代码。编写代码时,程序员需要预测执行代码期间可能发生的错误类型。 他们需要在代码中包含异常处理程序来解决这些错误。 从某种意义上说,异常处理程序允许程序员“防御”他们的代码。
(1)程序员想要通过使用异常处理程序来解决什么类型的错误?
•系统错误(例如,硬盘已满)
•数据错误(例如,试图复制主键值)
•用户操作错误(例如,数据输入错误)
•许多其他可能性!
(2)为什么异常处理很重要?
你能想到为什么异常处理很重要的原因吗?
一些原因包括:
•保护用户免受错误的影响(频繁的错误可能会阻止用户和/或导致用户退出应用程序。)
•保护数据库免遭错误(数据可能丢失或被覆盖。)
•重大错误需要大量系统资源(如果发生错误,纠正错误可能代价高昂;用户可能经常致电帮助台寻求帮助以解决错误。)
•代码更具可读性(错误处理例程可以写入发生错误的同一个块中。)
四、使用PL / SQL处理异常
块在PL / SQL引发异常时总是终止,但您可以指定异常处理程序在块结束之前执行最终操作。 异常部分以关键字EXCEPTION开头。
DECLAREv_country_name wf_countries.country_name%TYPE := 'Korea, South';v_elevation wf_countries.highest_elevation%TYPE;
BEGINSELECT highest_elevation INTO v_elevationFROM wf_countries WHERE country_name = v_country_name;
EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE ('Country name, '|| v_country_name ||',cannot be found. Re-enter the country name using the correctspelling.');
END;
当处理异常时,PL / SQL程序不会突然终止。
当引发异常时,控制转移到异常部分,并执行异常部分中的处理程序。 PL / SQL块终止正常,成功完成。
Country name, Korea, South,
Cannot be found. Re-enter the country name using the correct spelling.
Statement processed.
一次只能发生一个例外情况。 发生异常时,PL / SQL在离开块之前只处理一个处理程序。
点A处的代码不会执行,因为SELECT语句失败。
DECLAREv_country_name wf_countries.country_name%TYPE := 'Korea, South';v_elevation wf_countries.highest_elevation%TYPE;
BEGINSELECT highest_elevation INTO v_elevationFROM wf_countries WHERE country_name = v_country_name;DBMS_OUTPUT.PUT_LINE(v_elevation); -- Point A
EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE ('Country name, '|| v_country_name ||',cannot be found. Re-enter the country name using the correctspelling.');
END;
以下是另一个例子。 块中的select语句检索Stock Clerks的姓氏。
DECLAREv_lname VARCHAR2(15);
BEGINSELECT last_name INTO v_lnameFROM employees WHERE job_id = 'ST_CLERK';DBMS_OUTPUT.PUT_LINE('The last name of the ST_CLERK is : '||v_lname);
END;
但是,由于数据中存在多个ST_CLERK,因此会引发异常。
以下代码包含预定义Oracle服务器错误的处理程序,称为TOO_MANY_ROWS。您将在下一课中了解有关预定义服务器错误的更多信息。
DECLAREv_lname employees.last_name%TYPE;
BEGINSELECT last_name INTO v_lnameFROM employees WHERE job_id = 'ST_CLERK';DBMS_OUTPUT.PUT_LINE('The last name of the ST_CLERK is : '||v_lname);
EXCEPTIONWHEN TOO_MANY_ROWS THENDBMS_OUTPUT.PUT_LINE (' Your select statement retrieved multiple
rows. Consider using a cursor.');
END;
五、陷阱异常
可以通过在PL / SQL块的异常处理部分中包含相应的处理程序来处理或“陷入”任何错误。 句法:EXCEPTIONWHEN exception1 [OR exception2 . . .] THENstatement1;statement2;. . .[WHEN exception3 [OR exception4 . . .] THENstatement1;statement2;. . .][WHEN OTHERS THENstatement1;statement2;. . .]
每个处理程序由一个WHEN子句组成,该子句指定一个异常名称,然后是引发该异常时要执行的一系列语句。 您可以在EXCEPTION部分包含任意数量的处理程序来处理特定的异常。 但是,对于单个异常,您不能拥有多个处理程序。
在语法中:
•异常是预定义异常的标准名称或在声明部分中声明的用户定义异常的名称
•语句是一个或多个PL / SQL或SQL语句
•OTHERS是一个可选的异常处理条款,可以捕捉任何未明确处理的异常
六、其他异常处理程序
异常处理部分只捕获指定的异常; 除非使用OTHERS异常处理程序,否则任何其他异常都不会被捕获。OTHERS处理程序捕获所有尚未被捕获的异常。 如果使用,OTHERS必须是定义的最后一个异常处理程序。
考虑下面的例子:
•如果程序引发异常NO_DATA_FOUND,则会执行相应处理程序中的语句。
•如果引发异常TOO_MANY_ROWS,则执行相应处理程序中的语句。
•但是,如果发生其他异常,则会执行OTHERS异常处理程序中的语句。
EXCEPTIONWHEN NO_DATA_FOUND THENstatement1;...WHEN TOO_MANY_ROWS THENstatement2;...WHEN OTHERS THENstatement3;
七、捕获异常指南
在捕获异常时遵循以下准则:
•每当有可能发生错误时总是添加异常处理程序。 在计算,字符串操作和SQL数据库操作期间,错误尤其可能。
•尽可能处理命名的异常,而不是在异常处理程序中使用OTHERS。 了解预定义例外的名称和原因。
•使用不良数据组合来测试代码,以查看可能出现的错误。
•在异常处理程序中写出调试信息。
•仔细考虑每个异常处理程序是否应该提交事务,将其回滚或让其继续。 无论错误有多严重,您都希望使数据库保持一致状态并避免存储任何不良数据。