2011-02-18 4 views
2

여기에 제가 작성한 스크립트가 있으며 EXCEPTION 블록에 이상한 구문 오류가 있습니다. 예외 블록을 제거하면 스크립트가 제대로 컴파일됩니다. 하지만 곧 내가 그것을 다시는일부 구문 오류 - 찾을 수 없습니다.

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; 

내가 질문 등의 종류를 물어은 매우 성가신 알고있는 스크립트를 여기에 나에게 오류

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 

을 제공입니다 쓸하지만 난 오류가 무엇인지 알아낼 수 없습니까 그. 나는 Pl/SQL에서 lehman입니다.

+3

그래, 알아 냈어. 예외 블록은 루프의 마지막 블록이어야합니다. 이 ** IF INSTR ** statment 및 EXCEPTION 블록이 해당 IF 문에 있습니다. 그래서 나는 예외 블록의 시작 바로 전에 IF 문을 끝내었고 오류는 사라졌습니다. 누군가이 개념을 설명하는 데 마음을 댈 수 있습니까? –

+2

'EXCEPTION'은 블록의 마지막 부분이어야하지만'EXECUTE IMMEDIATE'에만 적용하고자한다면'BEGIN' /'END' 블록 안의'*'안에' IF INSTR ... END IF' 부분. 그것은 아마 당신이 원하는 것이 아닙니다. –

+0

감사합니다. 어떻게 대답 할 수 있을까요? 대답 : –

답변

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; 
+0

나는 그것을 이미 알았지 만 내 질문은 여전히 ​​"Execute immediate"또는 "BEGIN"문장에 대해 exceoption 절을 매치시키는 방법이 무엇인지 여전히 서있다. –

+3

EXCEPTION 절은 BEGIN (및 END)과 일치해야합니다. BEGIN 및 END는 완전한 PL/SQL 블록을 형성합니다 (EXCEPTION이 있거나 없음). PL/SQL 블록은 다른 구문과 겹칠 수 없습니다. BEGIN 뒤에 IF 블록을 시작하면 EXIFEPTION은 END IF 뒤에 와야합니다. 블록의 두 번째 버전에서는 BEGIN ... EXCEPTION ... END를 UPDATE 주변에 더 가깝게 배치하면 어떤 일이 일어나는지 명확하게 알 수 있습니다. –

관련 문제