2011-02-18 37 views
2

這是我寫的腳本,它在EXCEPTION塊有奇怪的語法錯誤。如果我刪除異常阻止腳本編譯正確。但沒有快我把它寫回它給了我錯誤一些語法錯誤 - 無法找出在哪裏

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 

這裏是腳本

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; 

我知道它很討厭問這類問題,但我無法找出錯誤是什麼那。我是Pl/SQL的萊曼。

+3

好吧,我猜我想通了。異常塊必須是循環中的最後一個塊。我有這個** IF INSTR **陳述和EXCEPTION塊在那個IF語句中。所以我在異常塊開始之前結束了IF語句,錯誤消失了。有人會介意解釋這個概念嗎? – 2011-02-18 17:00:38

+2

`EXCEPTION`必須是塊的最後一部分,但是如果你只希望它適用於`EXECUTE IMMEDIATE`,那麼你可以在它自己的`BEGIN` /`END`塊內* IF INSTR ... END IF`部分。雖然這可能不是你想要的。 – 2011-02-18 17:14:41

回答

3

錯誤似乎是您的EXCEPTION子句在IF INSTR (cc, '_') <> 0 IF語句中,但您似乎想將EXCEPTION與循環頂部的BEGIN語句匹配。我相信你想要移動END IF;爲IF INSTR (cc, '_') <> 0異常之前,我在這裏做

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; 

話雖這麼說,不過,我可能會重寫代碼位。承諾每500行幾乎肯定是一個錯誤。我非常懷疑你的WHEN OTHERS異常處理程序 - 我真的認爲你至少要將錯誤寫入表或填充錯誤集合,而不是寫入DBMS_OUTPUT緩衝區,可能會也可能不會被顯示。

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;