Search code examples
sqloracle-databaseplsqlora-06550

Some Syntax Error - Can't figure out where


Here is the script that i wrote and it has weird syntax error at EXCEPTION block. If i remove exception block the script compiles properly. but no sooner i write it back it gives me error

Error(58,11): PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:     ( begin case declare else elsif end exit for goto if loop mod    null pragma raise return select update while with    <an identifier> <a double-quoted delimited-identifier>    <a bind variable> << continue close current delete fetch lock    insert open rollback savepoint set sql execute commit forall    merge pipe purge 

Here is the script

LOOP
  BEGIN
    SAVEPOINT check_point;

    EXIT WHEN DBMS_SQL.FETCH_ROWS (cursor_handle) = 0;
    DBMS_SQL.COLUMN_VALUE (cursor_handle, 1,  cc , col_err, actual_len);
    DBMS_SQL.COLUMN_VALUE (cursor_handle, 2,  di, col_err, actual_len);

    IF INSTR (cc, '_') <> 0 THEN
      cc := Trim (cc);
      cc := Upper(cc);
      cc := substr(cc,4,2);

      EXECUTE IMMEDIATE 'UPDATE  ' || dest || ' SET cc = :v1 WHERE di = :v2' 
        USING cc, di;

      if SQL%ROWCOUNT > 0 THEN
        inserts := inserts + 1;
        counter := counter + 1;
        IF counter > 500 THEN
          counter := 0;
          COMMIT;
        END IF;
      END IF;

      EXCEPTION
        WHEN DUP_VAL_ON_INDEX THEN
          dups := dups+1;
          ROLLBACK TO check_point;
        WHEN VALUE_ERROR THEN
          valerr := valerr +1;
          ROLLBACK TO check_point;
        WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE('errno: ' || TO_CHAR(SQLCODE) || ' Msg: ' || SQLERRM);
          otherexc := otherexc +1;
        IF otherexc > 50 THEN 
          EXIT;
        END IF;
        ROLLBACK TO check_point;              
    END IF;
  END;
END LOOP;

I know its very annoying to ask such kind a question but i am unable to figure out what error is that. I am lehman at Pl/SQL.


Solution

  • The error appears to be that your EXCEPTION clause is inside the IF INSTR (cc, '_') <> 0 IF statements but you appear to want to match the EXCEPTION to the BEGIN statement at the top of your loop. I believe that you want to move the END IF; for the IF INSTR (cc, '_') <> 0 before the EXCEPTION as I do here

    LOOP
      BEGIN
        SAVEPOINT check_point;
    
        EXIT WHEN DBMS_SQL.FETCH_ROWS (cursor_handle) = 0;
        DBMS_SQL.COLUMN_VALUE (cursor_handle, 1,  cc , col_err, actual_len);
        DBMS_SQL.COLUMN_VALUE (cursor_handle, 2,  di, col_err, actual_len);
    
        IF INSTR (cc, '_') <> 0 THEN
          cc := Trim (cc);
          cc := Upper(cc);
          cc := substr(cc,4,2);
    
          EXECUTE IMMEDIATE 'UPDATE  ' || dest || ' SET cc = :v1 WHERE di = :v2' 
            USING cc, di;
    
          if SQL%ROWCOUNT > 0 THEN
            inserts := inserts + 1;
            counter := counter + 1;
            IF counter > 500 THEN
              counter := 0;
              COMMIT;
            END IF; -- IF counter > 500
          END IF; -- IF SQL%ROWCOUNT > 0
        END IF; -- INSTR (cc, '_') <> 0
    
    
      EXCEPTION
        WHEN DUP_VAL_ON_INDEX THEN
          dups := dups+1;
          ROLLBACK TO check_point;
        WHEN VALUE_ERROR THEN
          valerr := valerr +1;
          ROLLBACK TO check_point;
        WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE('errno: ' || TO_CHAR(SQLCODE) || ' Msg: ' || SQLERRM);
          otherexc := otherexc +1;
          IF otherexc > 50 THEN 
            EXIT;
          END IF;
          ROLLBACK TO check_point;              
      END;
    END LOOP;
    

    That being said, however, I would probably rewrite the code a bit. Committing every 500 rows is almost certainly an error. I'm very dubious of your WHEN OTHERS exception handler-- I would really think that you'd want to at least write the error to a table or populate a collection of errors rather than writing to the DBMS_OUTPUT buffer that may or may not ever be displayed.

    LOOP
      SAVEPOINT check_point;
    
      EXIT WHEN DBMS_SQL.FETCH_ROWS (cursor_handle) = 0;
      DBMS_SQL.COLUMN_VALUE (cursor_handle, 1,  cc , col_err, actual_len);
      DBMS_SQL.COLUMN_VALUE (cursor_handle, 2,  di, col_err, actual_len);
    
      IF INSTR (cc, '_') <> 0 THEN
        cc := Trim (cc);
        cc := Upper(cc);
        cc := substr(cc,4,2);
    
        BEGIN
          EXECUTE IMMEDIATE 'UPDATE  ' || dest || ' SET cc = :v1 WHERE di = :v2' 
            USING cc, di;
    
          if SQL%ROWCOUNT > 0 THEN
            inserts := inserts + 1;
          END IF; 
        EXCEPTION
          WHEN DUP_VAL_ON_INDEX THEN
            dups := dups+1;
            ROLLBACK TO check_point;
          WHEN VALUE_ERROR THEN
            valerr := valerr +1;
            ROLLBACK TO check_point;
          WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('errno: ' || TO_CHAR(SQLCODE) || ' Msg: ' || SQLERRM);
            otherexc := otherexc +1;
            IF otherexc > 50 THEN 
              EXIT;
            END IF;
            ROLLBACK TO check_point;              
        END;
    
      END IF; -- INSTR (cc, '_') <> 0
    END LOOP;