Oracle 查找异常(PL/SQL)

Oracle 查找异常(PL/SQL),oracle,plsql,exception-handling,Oracle,Plsql,Exception Handling,我正在Oracle中运行一段代码,要求用户输入路由类型,然后程序根据用户输入的路由以及获取的行数获取最长和最短的路由。我需要向代码中添加任何异常,我正在尝试考虑在这种情况下可以添加什么样的异常。我正在考虑添加一个异常,如果获取的行是,则会出现错误。您可以使用该过程在用户定义的范围-20000..-20999中引发特定异常,然后定义一个异常,以便捕获它。类似于以下的方法应该可以工作: DECLARE SOMETHING_UNWANTED_HAPPENS BOOLEAN := TRUE; BEG

我正在Oracle中运行一段代码,要求用户输入路由类型,然后程序根据用户输入的路由以及获取的行数获取最长和最短的路由。我需要向代码中添加任何异常,我正在尝试考虑在这种情况下可以添加什么样的异常。我正在考虑添加一个异常,如果获取的行是,则会出现错误。您可以使用该过程在用户定义的范围-20000..-20999中引发特定异常,然后定义一个异常,以便捕获它。类似于以下的方法应该可以工作:

DECLARE
  SOMETHING_UNWANTED_HAPPENS BOOLEAN := TRUE;
BEGIN
  IF SOMETHING_UNWANTED_HAPPENS THEN
    RAISE_APPLICATION_ERROR(-20001, 'Something I didn''t want happened');
  END IF;
EXCEPTION
  WHEN OTHERS THEN
    IF SQLCODE = -20001 THEN
      DBMS_OUTPUT.PUT_LINE('My user-defined exception was raised');
    -- Do whatever else you want to do to handle this exception
    ELSE
      DBMS_OUTPUT.PUT_LINE('Something else happened');
    END IF;
END;
或者您可以声明一个异常变量,用PRAGMA EXCEPTION_INIT初始化它,然后像使用任何其他异常一样使用它:

DECLARE
  my_exception EXCEPTION;
  PRAGMA EXCEPTION_INIT(my_exception, -20001);

  SOMETHING_UNWANTED_HAPPENS BOOLEAN := TRUE;
BEGIN
  IF SOMETHING_UNWANTED_HAPPENS THEN
    RAISE my_exception;
  END IF;
EXCEPTION
  WHEN my_exception THEN
    DBMS_OUTPUT.PUT_LINE('My user-defined exception was raised');

  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Something else happened');
END;
在这种情况下,它们是否合适

EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Data not found');


WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('This program encountered an error');
处理这样的异常被普遍认为是不好的做法。它吞噬了真正的异常,因此用户知道某些东西失败了,但他们完全不知道发生了什么

在这种情况下,什么都不做比什么都不做要好

在您的情况下,我建议您依赖默认的PL/SQL NO_DATA_FOUND异常来处理NO记录,并在只有一个记录时引发定制异常。大概是这样的:

DECLARE
    v_type VARCHAR2 (20);
    min_length NUMBER;
    max_length NUMBER;
    v_count NUMBER;
    -- user-defined exception
    x_single_route exception;
    pragme expcetion_init(x_single_route, -20001);

BEGIN
    v_type := '&InsertTypeRoute';

    IF v_type = 'Multi-Lane Divided' OR
        v_type = 'Paved Divided' OR
        v_type = 'Paved Undivided' 
    THEN
        SELECT MIN(LENGTH_KM), MAX(LENGTH_KM), COUNT(LENGTH_KM) INTO min_length, max_length, v_count
        FROM TBLROUTE WHERE TYPE = v_type;

    IF v_count > 1 THEN
        DBMS_OUTPUT.PUT_LINE('The minimum length is: ' || TO_CHAR(min_length));
        DBMS_OUTPUT.PUT_LINE('The maximum length is: ' || TO_CHAR(max_length));
        DBMS_OUTPUT.PUT_LINE ('Total number of '|| v_type ||' route is: ' || TO_CHAR(v_count));
    ELSE
        raise x_single_route;
    END IF;

EXCEPTION
    WHEN x_single_route THEN 
        DBMS_OUTPUT.PUT_LINE ('Route has only one leg');
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE ('Route type cannot be found'); 
END;
/ 
通常,提出异常是一种好的做法:用户希望知道什么时候出了问题。虽然这看起来是一个面向用户的程序,但它有点不同

   ... 
EXCEPTION
    WHEN x_single_route THEN 
        DBMS_OUTPUT.PUT_LINE ('Route has only one leg');
        RAISE;
    WHEN NO_DATA_FOUND THEN
        ....
如果您正在使用WHEN_OTHERS和RAISE,建议添加SQLCODE和SQLERRM 这将确切地告诉你出了什么问题

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR MESSAGE :' || SQLCODE || ' :' || SQLERRM );
RAISE;

我不确定我是否理解你问的问题。您是否询问如果SELECT INTO返回除1行以外的任何内容,会引发什么异常?如果查询返回的行数超过1行,则会出现“行数过多”异常;如果查询返回0行,则会出现“未找到数据”异常。这就是你要问的吗?还是你在问别的问题?一个没有IF的ELSE没有多大意义。异常是当其他人在传入已知参数和值的日志表和遇到错误的过程包中出现NULL写入错误时;内联您可以处理已知的错误,如当时没有找到数据或行太多,然后我会使用这种类型的逻辑来捕获所有错误并记录它们,这样我们就可以检查问题是否未被解释,并有日志来解决这些问题。我试图找到一个异常,如果路由类型有一行或多行,则会给我一个错误较少,因为每种路线类型应具有远远多于1条的记录。
   ... 
EXCEPTION
    WHEN x_single_route THEN 
        DBMS_OUTPUT.PUT_LINE ('Route has only one leg');
        RAISE;
    WHEN NO_DATA_FOUND THEN
        ....
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR MESSAGE :' || SQLCODE || ' :' || SQLERRM );
RAISE;