dee*_*dee 6 sql oracle plsql exception
我有一系列需要在Oracle包中使用的更新语句.这种情况很少见,但可能会出现偶然且不可避免的用户错误,导致其中一个更新语句抛出"单行子查询返回一行或多行"错误.
我一直在研究oracle PL/SQl的异常处理,我对如何以及使用什么来捕获这个异常有点困惑,因此包不会崩溃.
我知道预先构建的"Too Many Rows"异常条款存在,但我读到的所有内容似乎都说它用于不正确的插入语句.
我可以将此作为我的例外吗?或者我是否需要构建自己的异常子句.我以前从来没有自己建造一个,只是粗略地想知道在哪里放置所需的一切.
下面的代码基本上是如何在这个特定的过程中设置更新,但为了简洁起见,我只是使用一个简单的例子来说明它的外观.
INSERT INTO TempTable... --(Initial insert statement)
UPDATE TempTable t SET t.Row_one = (SELECT (Statement_One))
WHERE T.Row_One is NULL
UPDATE TempTable t SET t.Row_one = (SELECT (Statement_Two))
WHERE T.Row_One is NULL
UPDATE TempTable t SET t.Row_one = (SELECT (Statement_Three))
WHERE T.Row_One is NULL
-- Does the exception clause start here?
EXCEPTION
WHEN TOO_MANY_ROWS THEN
(What do I tell the Procedure to do here, what am I able to tell it to do?)
--end of updates that need the exception handling
-- more insert statements into other tables based on data from the preceding Temp Table
END;
Run Code Online (Sandbox Code Playgroud)
这会工作还是我需要构建自定义异常?
提前致谢.
首先,TOO_MANY_ROWS异常不会捕获select语句返回多行的情况.当您发出返回多行的SELECT .. INTO语句时,TOO_MANY_ROWS异常用于ORA-01422.您在案例中遇到的异常是ORA-01427,单行子查询返回多行.
如果要在过程中处理此特定错误,请使用EXCEPTION_INIT pragma将异常名称与错误相关联:
too_many_values EXCEPTION;
PRAGMA EXCEPTION_INIT(too_many_values, -1427);
Run Code Online (Sandbox Code Playgroud)
然后,您可以在异常处理程序中引用此名称:
EXCEPTION
WHEN TOO_MANY_VALUES THEN
{perform your handler here}
Run Code Online (Sandbox Code Playgroud)
你在处理程序中放置的内容取决于你的程序.很多时候,您需要向调用者返回某种错误代码/消息:
PROCEDURE my_proc(p_one VARCHAR2, p_err OUT VARCHAR2) IS
too_many_values EXCEPTION;
PRAGMA EXCEPTION_INIT(too_many_values, -1427);
BEGIN
...
EXCEPTION
WHEN TOO_MANY_VALUES THEN
p_err := 'More than one value available to assign in the update';
RAISE; -- re-raise the exception for the caller
WHEN OTHERS THEN
p_err := SQLERRM; -- return the oracle message for the unexpected error
RAISE;
END;
Run Code Online (Sandbox Code Playgroud)
另一种方法是跳过特定的异常处理程序并在WHEN OTHERS处理程序中返回通用的oracle消息:
EXCEPTION
WHEN OTHERS THEN
p_err := SQLERRM;
END;
Run Code Online (Sandbox Code Playgroud)
第一种方法的优点是,当流程的输出直接反馈给用户时,您可以自定义消息以使最终用户更友好.后一种方法的优点是涉及的编码较少.错误处理是任何应用程序的一个重要且经常受到限制的方面.
Oracle的文档就在这里.
编辑:
如果这是一个包,并且您希望避免通过一系列过程调用传递一长串错误变量,则可以使用包范围声明错误变量,在遇到错误时设置它,并再次升级错误.
PACKAGE BODY my_pkg is
g_err VARCHAR2(256);
PROCEDURE procx(... , p_err OUT VARCHAR2) IS...
...
proc_y(p1);
EXCEPTION
WHEN OTHERS THEN
p_err := NVL(g_err, SQLERRM);
END;
PROCEDURE proc_y(p1 VARCHAR2) IS
...
proc_z(p2);
END;
PROCEDURE proc_z(p2 VARCHAR2) IS
too_many_values EXCEPTION;
PRAGMA EXCEPTION_INIT(too_many_values, -1427);
BEGIN
....
EXCEPTION
WHEN TOO_MANY_VALUES THEN
g_err := 'More than one value available to assign in the update';
RAISE; -- re-raise the exception for the caller
END;
Run Code Online (Sandbox Code Playgroud)
当在proc_z中引发异常时,它会被处理然后再次引发.它通过proc_y传播回来(没有处理程序),然后在proc_x中返回给用户.未在全局g_err中设置的错误获取通用Oracle错误消息.这避免了必须在整个包中传递初始错误参数.