2015-11-11 5 views
0

У меня есть процедура в Oracle, я столкнулся с ошибкой, но она не меняет значение p_out_msg, почему это так? Вместо этого ошибка вернется к курсору.Oracle не выбрасывает исключение

Код:

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; 
+0

где анонимный блок, вызывающий процедуру? Можете ли вы опубликовать его? – brenners1302

+0

@ brenners1302 Я назвал его от разработчика SQL. – superigno

+0

Вы должны поймать ошибку до того, как она откроет курсор. сначала попробуйте сохранить дату в переменной. Затем используйте переменную в условии. Так что, когда процедура пытается преобразовать дату и сохранить ее в переменной и генерирует ошибку, она перейдет непосредственно к исключению. – brenners1302

ответ

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; 
+0

Отлично! Спасибо! – superigno

+0

Обратите внимание, что когда вы выполняете 'FETCH p_out_cur INTO l_rec;' внутри процедуры, вы также «освобождаете» первую запись в вызывающем блоке. –

Смежные вопросы