简体   繁体   中英

Stored procedure is not returning expected custom exception message

I am using this stored procedure in which I am checking if cursor contains any data and if it has 0 records then raise the exception else return the data into the output.

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; 

This stored procedure is throwing an exception if data is not present. But instead of returning custom exception message, it is returning a system exception:

ORA-01403: no data found

Am I doing anything wrong here? Is there any changes which needs to be done to return custom exception message ie "Data Not Found"? I am going to modify this message. Earlier I was using below SP but it was not returning any error message in case of 0 records because of that I have done the changes as mentioned in the stored procedure:

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; 

ORA-01403: no data found is raised from either of the two select statements before you BULK COLLECT from the CURSOR .

Apart from that, your code seems to contain several redundant constructs to make it unnecessarily complex . For instance, the only purpose of CURSOR cc is to define a table variable of that type and using BULK COLLECT is not needed if your intention is to simply check if records exist before opening a cursor.

You could rewrite it this way.

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; 
/ 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM