我正在编写一个存储过程,需要对其进行很多调节。通过C#.NET编码的一般知识,异常可能会损害性能,我一直避免在PL / sql中使用它们。我在这个存储过程中的调理主要围绕着是否存在一个记录,我可以通过两种方法之一进行操作:
SELECT COUNT(*) INTO var WHERE condition; IF var > 0 THEN SELECT NEEDED_FIELD INTO otherVar WHERE condition; ....
-要么-
SELECT NEEDED_FIELD INTO var WHERE condition; EXCEPTION WHEN NO_DATA_FOUND ....
第二种情况对我来说似乎更为优雅,因为那时我可以使用NEEDED_FIELD,在第一种情况下,我将不得不在第一条语句中选择该条件。较少的代码但是如果存储过程使用COUNT(*)运行得更快,那么我不介意再打一点点来弥补处理速度。
任何提示?我是否还有另一种可能性?
编辑
我应该提到这一切都已经嵌套在FOR LOOP中。不知道这是否与使用游标有所不同,因为我不认为我可以将光标DECLARE作为FOR LOOP中的选择。
我不会使用显式光标来做到这一点。当可以使用隐式游标时,Steve F.不再建议人们使用显式游标。
count(*)的方法是不安全的。如果另一个会话删除符合count(*)行之后的条件的行,并且在使用select … into的行之前,该代码将抛出一个不会被处理的异常。
从原始帖子的第二个版本没有这个问题,通常是首选。
也就是说,有一个小的开销使用异常,如果你100%肯定数据不会改变,你可以使用计数(*),但我建议反对它。
我在32位Windows上的Oracle 10.2.0.1上运行了这些基准测试。我只是看着经过的时间。还有其他测试线束可以提供更多的细节(例如锁存计数和使用的内存)。
sql>create table t (NEEDED_FIELD number,COND number);
Table created.
sql>insert into t (NEEDED_FIELD,cond) values (1,0);
1 row created.
declare otherVar number; cnt number; begin for i in 1 .. 50000 loop select count(*) into cnt from t where cond = 1; if (cnt = 1) then select NEEDED_FIELD INTO otherVar from t where cond = 1; else otherVar := 0; end if; end loop; end; /
PL/sql procedure successfully completed.
Elapsed: 00:00:02.70
declare otherVar number; begin for i in 1 .. 50000 loop begin select NEEDED_FIELD INTO otherVar from t where cond = 1; exception when no_data_found then otherVar := 0; end; end loop; end; /
PL/sql procedure successfully completed.
Elapsed: 00:00:03.06