关于Oracle中忽视、锁定和解析问题分析
本问对一些技术人员常关注的WHEN OTHERS、锁定、级联和解析的问题进行了深入解析……
【IT专家网独家】有一个程序结构,在PL/SQL中采用了我不希望采用的WHEN OTHERS。
这个条件用在一个异常块中时,可以捕获任何未处理的异常。有些时候这是很有用的,例如对于日志错误:
| exception when others then log_error(....); raise; end; |
但是我看到的问题是太多人使用WHEN OTHERS条件而没有在它之后调用RAISE或RAISE_APPLICATION_ERROR。这很大程度上掩盖了错误。在现实中,错误发生了,但是没有采用任何有效的方法进行处理;它只是被默默的忽视了。你的代码的使用者不知道某些东西发生了严重错误,而你的代码失败了,他或她通常以为一切都运行的很好。
在Ask Tom(asktom.oracle.com)上,我看到关于这个错误的提问和回答不断的出现。例如,我最近收到了这样一个问题:
我创建了一个包,它将10个工作包括相关数据批量加载到一个文本文件中。我需要使用UTL_FILE,因为在这个过程中,我调用了三个存储过程来获取一些数据。这个过程将批量加载9,500,000个字符串到文件中,这个过程的总时间为六个小时。我需要你的建议,因为我需要降低总时间。
这是代码:
| PROCEDURE prcl_MakeFile(...) IS ... variables ... BEGIN l_FileID := UTL_FILE.FOPEN (...); OPEN cur; LOOP ... process records here ... ... lots of code ... END LOOP; CLOSE cur; UTL_FILE.FCLOSE(l_FileID); EXCEPTION WHEN OTHERS THEN IF (UTL_FILE.IS_OPEN(l_FileID)) THEN UTL_FILE.FCLOSE(l_FileID); END IF; END prcl_MakeFile; |
我的回答很简单:我可以使这个代码运行得非常快。所有这个存储过程所要做的是
| PROCEDURE prcl_MakeFile(...) IS ... variables... BEGIN Return; END prcl_MakeFile; |
这两个存储过程在逻辑上是等价的,但是我的快的多!那么为什么它们是逻辑等价的呢?这完全是因为在存储过程中的WHEN OTHERS代码——WHEN OTHERS条件后没有跟着RAISE或RAISE_APPLICATION_ERROR。假设在过程中调用UTL_FILE .FOPEN失败——会发生什么呢?所有这些代码会被跳过,但是没有人知道。如果你有代码封装了一个包含WHEN OTHERS的异常块——但不引起异常——那么我认为在异常块中的代码都可以安全的删除。你不需要它,因为如果代码执行失败,你会忽视它执行失败的事实。如果这代码允许有时可以不执行,那么事实上你可以让它永远不执行。你不能依赖于这个代码事实上在运行,那你就没有必要执行它。
我还认为不运行这代码会比运行它更安全。至少如果你不运行它,你知道数据库会是处于什么状态。如果你调用了包含WHEN OTHERS结构(没有引起异常)的代码段,那么就不知道数据库将处于什么状态。例如,假定有下面的存储过程:
| procedure p is begin insert into t1 values(1); insert into t2 values(2); insert into t3 values(3); exception when others then dbms_output.put_line ('something bad happened!'); end; |
- 本文关键词:

