sqloracle-databaseplsqloracle12cpls-00103

Encountered the symbol "EXCEPTION" error in stored procedure


I am programming a procedure in an Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production.

I have an exception inside a LOOP because I don't want the procedure to exit the LOOP if an exception is thrown.

create or replace procedure PARSE_REGISTER_MESSAGE
  IS

        HOTELS_TO_PROCESS number := 5000;     

        cursor unparsed_messages is

         SELECT REGISTER_psd_id, message

         FROM
            ( SELECT REGISTER_psd_id, message
              FROM cc_owner.REGISTER_psd
              WHERE parsed != 1
                    OR parsed IS NULL
              ORDER BY CREATION_DATE DESC)

         WHERE rownum < HOTELS_TO_PROCESS;

    BEGIN

     FOR psd_rec in unparsed_messages
     LOOP

p_msg.parse_msg (psd_rec.REGISTER_psd_id, null, psd_rec.message);

         EXCEPTION

        WHEN OTHERS
        THEN 
        DECLARE
            l_code   INTEGER := SQLCODE;
        BEGIN

            of_owner.p_db_trc.add_error
                 ( 'PARSE_REGISTER_MESSAGE','', 
                    l_code, 
                    sys.DBMS_UTILITY.format_error_stack, 
                    sys.DBMS_UTILITY.format_error_backtrace, 
                    sys.DBMS_UTILITY.format_call_stack ); 

        END;

    END LOOP;

END;

But I can't compile the package due this error:

Error(25,10): PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:
( begin case declare end exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge

I Also tried:

create or replace procedure PARSE_REGISTER_MESSAGE
  IS

        HOTELS_TO_PROCESS number := 5000;     

        cursor unparsed_messages is

         SELECT REGISTER_psd_id, message

         FROM
            ( SELECT REGISTER_psd_id, message
              FROM cc_owner.REGISTER_psd
              WHERE parsed != 1
                    OR parsed IS NULL
              ORDER BY CREATION_DATE DESC)

         WHERE rownum < HOTELS_TO_PROCESS;

         psd_rec unparsed_messages%ROWTYPE;

    BEGIN

     FOR psd_rec in unparsed_messages
     LOOP
        BEGIN

          p_msg.parse_msg (psd_rec.REGISTER_psd_id, null, psd_rec.message);

         EXCEPTION

        WHEN OTHERS
        THEN 
        DECLARE
            l_code   INTEGER := SQLCODE;
        BEGIN

            of_owner.p_db_trc.add_error
                 ( 'PARSE_REGISTER_MESSAGE','', 
                    l_code, 
                    sys.DBMS_UTILITY.format_error_stack, 
                    sys.DBMS_UTILITY.format_error_backtrace, 
                    sys.DBMS_UTILITY.format_call_stack ); 

        END;

    END LOOP;

END;

But then I got this error:

Error(48,4): PLS-00103: Encountered the symbol ";" when expecting one of the following:     loop 

Solution

  • The syntax for a PLSQL block / procedure is :

    DECLARE
     -- Here you declare all the varaible used in block
    BEGIN
     -- Here you write the body of the Block
    EXCEPTION
     -- Here you write the exceptions which you want to handle.
    END;
    

    Now when i look at your code, you have written Exception block inside the FOR LOOP, which will work only if you use the above syntax. In you case the scope of Exception block is not identified by Oracle and hence it throws error.

     FOR psd_rec IN unparsed_messages
       LOOP
          p_msg.parse_msg (psd_rec.REGISTER_psd_id, NULL, psd_rec.MESSAGE);         
    
          EXCEPTION  --<-- Wrong way of using Excepton block. Scope of this Exception block is not resolved
            WHEN OTHERS
            THEN
            DECLARE
                l_code   INTEGER := SQLCODE;
            BEGIN
                of_owner.p_db_trc.add_error
                     ( 'PARSE_REGISTER_MESSAGE','',
                        l_code,
                        sys.DBMS_UTILITY.format_error_stack,
                        sys.DBMS_UTILITY.format_error_backtrace,
                        sys.DBMS_UTILITY.format_call_stack );
    
            END;
    

    You must modify your code as below to include the Exception block in for loop;

      CREATE OR REPLACE PROCEDURE PARSE_REGISTER_MESSAGE
        IS
           HOTELS_TO_PROCESS   NUMBER := 5000;
           l_code              INTEGER := SQLCODE;
    
           CURSOR unparsed_messages
           IS
              SELECT REGISTER_psd_id, MESSAGE
                FROM (  SELECT REGISTER_psd_id, MESSAGE
                          FROM cc_owner.REGISTER_psd
                         WHERE parsed != 1 OR parsed IS NULL
                      ORDER BY CREATION_DATE DESC)
               WHERE ROWNUM < HOTELS_TO_PROCESS;
        BEGIN
           FOR psd_rec IN unparsed_messages
           LOOP
              BEGIN
                 p_msg.parse_msg (psd_rec.REGISTER_psd_id, NULL, psd_rec.MESSAGE);
              EXCEPTION
                 WHEN OTHERS
                 THEN
                    of_owner.p_db_trc.add_error (
                       'PARSE_REGISTER_MESSAGE',
                       '',
                       l_code,
                       sys.DBMS_UTILITY.format_error_stack,
                       sys.DBMS_UTILITY.format_error_backtrace,
                       sys.DBMS_UTILITY.format_call_stack);
              END;
           END LOOP;
     EXCEPTION
       WHEN OTHERS
       THEN
          DBMS_OUTPUT.put_line (SQLERRM);    
    END;
    

    You second try has missing END statement and thats why you were getting error. See below:

    CREATE OR REPLACE PROCEDURE PARSE_REGISTER_MESSAGE
    IS
       HOTELS_TO_PROCESS   NUMBER := 5000;
       l_code              INTEGER := SQLCODE;
    
       CURSOR unparsed_messages
       IS
          SELECT REGISTER_psd_id, MESSAGE
            FROM (  SELECT REGISTER_psd_id, MESSAGE
                      FROM cc_owner.REGISTER_psd
                     WHERE parsed != 1 OR parsed IS NULL
                  ORDER BY CREATION_DATE DESC)
           WHERE ROWNUM < HOTELS_TO_PROCESS;
    
       psd_rec             unparsed_messages%ROWTYPE;
    BEGIN
       FOR psd_rec IN unparsed_messages
       LOOP
          BEGIN
             p_msg.parse_msg (psd_rec.REGISTER_psd_id, NULL, psd_rec.MESSAGE);
          EXCEPTION
             WHEN OTHERS
             THEN
                BEGIN
                   of_owner.p_db_trc.add_error (
                      'PARSE_REGISTER_MESSAGE',
                      '',
                      l_code,
                      sys.DBMS_UTILITY.format_error_stack,
                      sys.DBMS_UTILITY.format_error_backtrace,
                      sys.DBMS_UTILITY.format_call_stack);
                END;
          END;
       END LOOP;
    END;