Oracle存储过程 - 如果没有被捕获,raise_application_error会禁用该过程吗?

时间:2014-06-11 22:18:42

标签: oracle

我在Oracle中有一个存储过程:

SELECT Count(*) INTO v_count_of_rows_bad FROM SCHMEA.TABLE WHERE
KEY1   = v_key1
AND KEY2 = v_key2
AND STATUS IN ('0', 'P', 'N');

IF v_count_of_rows_bad > 0 THEN
   raise_application_error( -20001, 'Status is not ready' );
END IF;

目的是防止SP在状态为其中之一时更新记录。有一个批处理过程将针对行运行,并在完成时将状态更新为Y.只有在此之后才允许SP更新该行。 (我知道可能有更好的方法来做到这一点,但我坚持使用一些遗留的东西,另一个团队控制批处理过程。)

我没有在存储过程中捕获异常,而是使用它将文本“Status it not ready”传输到我正在调用该过程的.NET Web服务(用C#编写)。

问题是,一旦遇到错误,它似乎就会卡住。即使我手动将状态更新为表中的Y,并且看到它确实更新了,当我再次运行我的.NET服务时,它再次给我错误。但是,如果我再次运行创建或替换存储过程的SQL,那么运行webservice,它就不再“卡住”了。或者如果我只是再次编译SP,则修复它。有谁知道这可能是什么?

2 个答案:

答案 0 :(得分:1)

不,在存储过程中引发异常并不会导致Oracle卡住"卡住"。但是异常将返回给调用者,调用者需要适当地处理异常,例如,ROLLBACK当前事务,并关闭连接(或将其返回到连接池。)

目前尚不清楚为什么重新编译存储过程会导致应用程序变得“松散”#34;。提供的信息不足以明确解释您正在观察的行为。 (正如Justin在他的评论中指出的那样,有几种可能性(事务隔离级别,未提交的事务,隐式提交,缓存的结果集等)。

答案 1 :(得分:0)

除非你真的想要,否则你不必在这种情况下提出异常;你可以只对UPDATE进行编码,这样如果状态是不合需要的值之一,它就不会做任何事情:

UPDATE A_SCHEMA.SOME_TABLE
  SET SOME_COL = vVALUE,
      SOME_OTHER_COL = vOTHER_VALUE,
      ETC = vBLAH
  WHERE KEY1 = v_key1 AND
        KEY2 = v_key2 AND
        STATUS NOT IN ('0', 'P', 'N');

如果您需要知道是否有任何行已更新,您可以使用%ROWCOUNT,如

IF SQL%ROWCOUNT > 0 THEN
  DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' rows updated');
ELSE
  DBMS_OUTPUT.PUT_LINE('No rows updated! Run! Run for your lives!!');
END IF;

这几乎肯定比执行SELECT COUNT(*)...(速度可能非常慢)和然后转身并执行UPDATE更快。

分享并享受。