Oracle没有捕获异常

时间:2015-11-11 02:50:05

标签: oracle exception exception-handling procedure

我在Oracle中有一个程序,我遇到了错误,但它没有改变p_out_msg的值,为什么会这样?该错误转移到光标。

代码:

PROCEDURE get_proj(p_date    IN VARCHAR2,
                   p_out_cur OUT sys_refcursor,
                   p_out_msg OUT VARCHAR2)
IS 
BEGIN
  OPEN p_out_cur FOR 
    SELECT *
      FROM table t
     WHERE TO_DATE(p_date, 'DD-MM-YYYY HH24:MI:SS') = t.date

  p_out_msg := 'SUCCESS';

EXCEPTION
   WHEN OTHERS THEN
     p_out_msg := SUBSTR('An error was encountered: '||SQLERRM, 1, 250);

END get_proj;

说我输入的日期无效:

输出:

p_out_cur: ORA-01858: a non-numeric character was found where a numeric was expected

p_out_msg: SUCCESS

以下是@brenners1302所要求的匿名阻止:

DECLARE
  P_DATE VARCHAR2(200);
  P_OUT_CUR sys_refcursor;
  P_OUT_MSG VARCHAR2(200);
BEGIN
  P_DATE := '1111';

  PACKAGE_TEST.GET_PROJ(
    P_DATE => P_DATE,
    P_OUT_CUR => P_OUT_CUR,
    P_OUT_MSG => P_OUT_MSG
  );

  DBMS_OUTPUT.PUT_LINE(P_OUT_MSG); --SUCCESS

END;

1 个答案:

答案 0 :(得分:3)

当您使用OPEN p_out_cur FOR打开游标时,此时查询SELECT * FROM ...尚未执行,而只是与游标变量相关联。因此,从FETCH开始p_out_cur时可能会出现异常,因为这是关联查询开始执行的时间。

最简单的方法是以这种方式改变你的程序。

PROCEDURE get_proj(p_date    IN VARCHAR2,
                   p_out_cur OUT sys_refcursor,
                   p_out_msg OUT VARCHAR2)
IS 
 l_rec myTable%ROWTYPE;
BEGIN
       OPEN p_out_cur FOR 
        SELECT *
          FROM myTable t
         WHERE TO_DATE(p_date, 'DD-MM-YYYY HH24:MI:SS') = t.date

      -- at this point we can get an exception
      FETCH p_out_cur INTO l_rec;

      p_out_msg := 'SUCCESS';

EXCEPTION
   WHEN OTHERS THEN
       p_out_msg := SUBSTR('An error was encountered: '||SQLERRM, 1, 250);    
END get_proj;

所以是的,这意味着当你打开引用光标并将其传递给“外部世界”时,尝试获取它的人可以获得异常。在将参数传递给与游标关联的SQL中使用的函数之前,可以使用检查参数来减少此类情况的数量。例如,

PROCEDURE get_proj(p_date    IN VARCHAR2,
               p_out_cur OUT sys_refcursor,
               p_out_msg OUT VARCHAR2)
IS 
 l_normal_date DATE;
BEGIN
       -- if p_date has wrong format we better find it out
       -- before using it in a query
       l_normal_date := TO_DATE(p_date, 'DD-MM-YYYY HH24:MI:SS');

       OPEN p_out_cur FOR 
        SELECT *
          FROM myTable t
         WHERE l_normal_date = t.date

      p_out_msg := 'SUCCESS';

EXCEPTION
   WHEN OTHERS THEN
       p_out_msg := SUBSTR('An error was encountered: '||SQLERRM, 1, 250);    
END get_proj;