存储过程未返回预期的自定义异常消息

时间:2019-01-05 11:21:53

标签: sql oracle

我正在使用此存储过程,在该过程中,我检查游标是否包含任何数据,是否有0条记录,然后引发异常,否则将数据返回到输出中。

CREATE OR replace PROCEDURE user_details(v_ownerid    IN NUMBER, 
                                             v_branchcode IN NVARCHAR2, 
                                             v_login      IN NVARCHAR2, 
                                             cv_1         OUT SYS_REFCURSOR) 
IS 
  result_out1   SYS_REFCURSOR; 
  v_territoryid NUMBER(10); 
  v_user        NUMBER(10); 
  CURSOR cc IS 
    SELECT Z.username AS USERNAME, 
           Z.loginid  AS LOGINID, 
           Z.userid   AS CRMUSERID 
    FROM   userterritory U 
           inner join teammembers T 
                   ON U.ownerid = T.ownerid 
                      AND U.userid = T.memberid 
           inner join az_user Z 
                   ON Z.appownerid = T.ownerid 
                      AND Z.userid = T.memberid; 
  TYPE tbl_join 
    IS TABLE OF cc%ROWTYPE; 
  l_table       TBL_JOIN; 
BEGIN 
    SELECT regionid 
    INTO   v_territoryid 
    FROM   regions 
    WHERE  ownerid = v_ownerid 
           AND categorytype = 3 
           AND code = v_branchcode; 

    SELECT userid 
    INTO   v_user 
    FROM   az_user 
    WHERE  appownerid = v_ownerid 
           AND loginid = v_login; 

    OPEN result_out1 FOR 
      SELECT Z.username AS USERNAME, 
             Z.loginid  AS LOGINID, 
             Z.userid   AS CRMUSERID 
      FROM   userterritory U 
             inner join teammembers T 
                     ON U.ownerid = T.ownerid 
                        AND U.userid = T.memberid 
             inner join az_user Z 
                     ON Z.appownerid = T.ownerid 
                        AND Z.userid = T.memberid 
      WHERE  Z.appownerid = v_ownerid 
             AND T.reportsto = v_user 
             AND U.territoryid = v_territoryid; --using whereClause;      
    FETCH result_out1 bulk collect INTO l_table; 

--    FETCH result_out1 bulk collect INTO l_table; 

    dbms_output.Put_line('Count ' 
                         || l_table.count); 

    IF l_table.count > 0 THEN 
      OPEN cv_1 FOR 
        SELECT Z.username AS USERNAME, 
               Z.loginid  AS LOGINID, 
               Z.userid   AS CRMUSERID 
        FROM   userterritory U 
               inner join teammembers T 
                       ON U.ownerid = T.ownerid 
                          AND U.userid = T.memberid 
               inner join az_user Z 
                       ON Z.appownerid = T.ownerid 
                          AND Z.userid = T.memberid 
        WHERE  Z.appownerid = v_ownerid 
               AND T.reportsto = v_user 
               AND U.territoryid = v_territoryid; 
    ELSE 
      Raise_application_error(-20001, 'Data Not Found.'); 
    END IF; 
END; 

如果没有数据,此存储过程将引发异常。但是,它没有返回自定义异常消息,而是返回了系统异常:

  

ORA-01403:找不到数据

我在这里做错什么了吗?返回自定义异常消息(即“未找到数据”)是否需要做任何更改?我将修改此消息。之前我使用的是SP以下版本,但是在记录为0的情况下它没有返回任何错误消息,因为我已经按照存储过程中的说明进行了更改:

CREATE OR replace PROCEDURE user_details(v_ownerid    IN NUMBER, 
                                             v_branchcode IN NVARCHAR2, 
                                             v_login      IN NVARCHAR2, 
                                             cv_1         OUT SYS_REFCURSOR) 
AS 
  v_territoryid NUMBER(10); 
  v_user        NUMBER(10); 
BEGIN 
    SELECT regionid 
    INTO   v_territoryid 
    FROM   regions 
    WHERE  ownerid = v_ownerid 
           AND categorytype = 3 
           AND code = v_branchcode; 

    SELECT userid 
    INTO   v_user 
    FROM   az_user 
    WHERE  appownerid = v_ownerid 
           AND loginid = v_login; 

    OPEN cv_1 FOR 
      SELECT Z.username AS USERNAME, 
             Z.loginid  AS LOGINID, 
             Z.userid   AS CRMUSERID 
      FROM   userterritory U 
             inner join teammembers T 
                     ON U.ownerid = T.ownerid 
                        AND U.userid = T.memberid 
             inner join az_user Z 
                     ON Z.appownerid = T.ownerid 
                        AND Z.userid = T.memberid 
      WHERE  Z.appownerid = v_ownerid 
             AND T.reportsto = v_user 
             AND U.territoryid = v_territoryid; 
END; 

1 个答案:

答案 0 :(得分:0)

在您从ORA-01403: no data found BULK COLLECT之前,从两个选择语句中的任意一个引发

CURSOR

除此之外,您的代码似乎包含一些多余的构造,以使其不必要地变得复杂。例如,CURSOR cc的唯一目的是定义该类型的表变量,如果您只是想在打开游标之前检查记录是否存在,则不需要使用BULK COLLECT

您可以用这种方式重写它。

CREATE OR replace PROCEDURE user_details (v_ownerid    IN NUMBER, 
                                          v_branchcode IN NVARCHAR2, 
                                          v_login      IN NVARCHAR2, 
                                          cv_1         OUT SYS_REFCURSOR) 
IS 
  v_territoryid NUMBER(10); 
  v_user        NUMBER(10); 
  l_count       INT; 
BEGIN 
    SELECT regionid 
    INTO   v_territoryid 
    FROM   regions 
    WHERE  ownerid = v_ownerid 
           AND categorytype = 3 
           AND code = v_branchcode; 

    SELECT userid 
    INTO   v_user 
    FROM   az_user 
    WHERE  appownerid = v_ownerid 
           AND loginid = v_login; 

    SELECT CASE 
             WHEN EXISTS (SELECT 1  --check if a row exists.
                          FROM   userterritory u 
                                 INNER JOIN teammembers t 
                                         ON u.ownerid = t.ownerid 
                                            AND u.userid = t.memberid 
                                 INNER JOIN az_user z 
                                         ON z.appownerid = t.ownerid 
                                            AND z.userid = t.memberid 
                          WHERE  z.appownerid = v_ownerid 
                                 AND t.reportsto = v_user 
                                 AND u.territoryid = v_territoryid) THEN 1 
             ELSE 0 
           END 
    INTO   l_count 
    FROM   dual; 

    IF l_count = 1 THEN 
      OPEN cv_1 FOR 
        SELECT z.username AS username, 
               z.loginid  AS loginid, 
               z.userid   AS crmuserid 
        FROM   userterritory u 
               INNER JOIN teammembers t 
                       ON u.ownerid = t.ownerid 
                          AND u.userid = t.memberid 
               INNER JOIN az_user z 
                       ON z.appownerid = t.ownerid 
                          AND z.userid = t.memberid 
        WHERE  z.appownerid = v_ownerid 
               AND t.reportsto = v_user 
               AND u.territoryid = v_territoryid; 
    ELSE 
      raise_application_error(-20001, 'Data Not Found.'); 
    END IF; 
EXCEPTION 
  WHEN no_data_found THEN 
             raise_application_error(-20001, 'regionid or userid not Found.'); 
        -- Handling the exception  
        --for errors from first 2 selects 
END; 
/