我有如下所示的程序,但是当运行阻止时,如果找不到数据,则不会显示错误消息。
CREATE OR REPLACE
PROCEDURE DDPROJ_SP
(P_IDPROJ IN DD_PROJECT.IDPROJ%TYPE,
P_INFO OUT VARCHAR2,
p_check OUT VARCHAR2)
IS
CURSOR cur_ddproj IS
SELECT *
FROM dd_project
WHERE idproj = p_idproj;
lv_projinfo_txt VARCHAR2(100);
BEGIN
FOR rec_ddproj IN cur_ddproj LOOP
lv_projinfo_txt := (rec_ddproj.idproj||', '||rec_ddproj.projname||
', '||rec_ddproj.projstartdate||', '||rec_ddproj. projenddate||
', '||rec_ddproj.projfundgoal||', '||rec_ddproj.p rojcoord);
END LOOP;
P_INFO := LV_PROJINFO_TXT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
P_CHECK :='Please select another project';
DBMS_OUTPUT.PUT_LINE(P_CHECK);
END;
并阻止:
DECLARE
LV_INFO_TXT VARCHAR2(100);
LV_CHECK_TXT VARCHAR2(30);
BEGIN
DDPROJ_SP(00,lv_info_txt,lv_check_txt);
DBMS_OUTPUT.PUT_LINE(LV_INFO_TXT);
END;
在RUNNING BLOCK之后如果提供的ID是正确的,我会收到请求的信息,但是如果找不到ID,则异常不会在打印时显示消息。
答案 0 :(得分:3)
首先,正如已经指出的那样,除了调用dbms_output
之外,您的异常处理程序不会执行任何真正可见的操作,您只能看到set serverout on
或者dbms_output
或否则从FOR
访问结果。
其次,更重要的是,当您使用NO_DATA_FOUND
循环来处理游标的结果时,永远不会引发...
end loop;
if lv_projinfo_txt is null then
raise no_data_found;
end if;
异常。
如果您想检测未找到任何行,您可以选择以下几种方法:
循环后,检查变量是否已设置,例如:
FOR
如果您不希望查询找到多于1条记录(由您的谓词建议" id"),则可以避免{{1 }循环并使用简单的select into
:
PROCEDURE DDPROJ_SP
(P_IDPROJ IN DD_PROJECT.IDPROJ%TYPE,
P_INFO OUT VARCHAR2,
p_check OUT VARCHAR2)
IS
rec_ddproj dd_project%rowtype;
lv_projinfo_txt VARCHAR2(100);
BEGIN
SELECT *
into rec_ddproj
FROM dd_project
WHERE idproj = p_idproj;
lv_projinfo_txt := (rec_ddproj.idproj||', '||rec_ddproj.projname||
', '||rec_ddproj.projstartdate||', '||rec_ddproj.projenddate||
', '||rec_ddproj.projfundgoal||', '||rec_ddproj.projcoord);
P_INFO := LV_PROJINFO_TXT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
P_CHECK :='Please select another project';
DBMS_OUTPUT.PUT_LINE(P_CHECK);
END;
注意:
select into
可能会引发NO_DATA_FOUND
或TOO_MANY_ROWS
。
良好做法是永远不会在不重新引发异常的情况下处理错误,除非您的代码实际处理异常。在您的情况下,您的代码只是通过p_check
参数将信号发送回调用进程,该参数将处理错误的责任移交给调用者。在某些情况下这可能没问题,但它假设呼叫者实际上听到了信号。提出一个强制调用者适当处理它的异常会更好。
好的做法是对查询中的所有列和参数进行别名;拥有像idproj = p_idproj
这样的SQL谓词可以假设该表将来永远不会有一个名为p_idproj
的列。相反,有意识地对所有列和参数进行别名,例如
SELECT x.*
into rec_ddproj
FROM dd_project x
WHERE x.idproj = ddproj_sp.p_idproj;