我在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;
答案 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;