2016-11-28 9 views
0

커서를 통해 반복되는 일부 절차가있는 아래 절차가 있습니다. 다른 세션의 누군가가 동일한 세트를 업데이트하려고하는 경우에 대비하여 커서에 FOR UPDATE NOWAIT를 삽입하여 레코드 세트를 잠급니다.루프에서 Oracle PL/SQL 캡처 잠금 예외가 발생하고 계속됩니다.

그러나 내가 커서에서 선택한 레코드가 누군가에 의해 잠겨져있는 경우가있을 수 있습니다.이 경우 단순히 잠긴 레코드를 로그 테이블에 기록하고 다음 레코드로 계속 진행합니다. 루프.

PROCEDURE test(p_id IN NUMBER) 
IS 

    CURSOR cur_test IS 
    SELECT emp_id, 
     emp_name 
    FROM 
     EMP 
    FOR UPDATE NOWAIT; 

    row_locked EXCEPTION; 
    PRAGMA EXCEPTION_INIT(row_locked, -54); 

BEGIN 
    FOR r_cur_test IN cur_test 
    LOOP 
    BEGIN 

     --do something 

    EXCEPTION 
     WHEN row_locked THEN 
     --log locked record in log table 
     log_lock('Record is locked'); 
     COMMIT; 
    END;  
    END LOOP; 

    --call log function to log a successful run 

    COMMIT; 
EXCEPTION 
    WHEN OTHERS THEN 
    --Unsuccessful completion of the run.Trap all unhandled exceptions. 
    --log error in error table  
    log_lock('Process exited with error'); 
    ROLLBACK; 

END; 

테스트를 위해, 나는 세션 1을 열고 세션 2에서

select * from EMP FOR UPDATE NOWAIT 

및 실행, 나는 결과로, 항상 다른 예외에 갔다

begin 
    test(1); 
end; 

을 실행하는 중 프로 시저가 커서를 계속 반복하지 않고 종료되었습니다.

아무도 나에게 조언을 해줄 수 있습니까? 덕분에 많은

+2

글쎄, 다른 사람이 차단할 때의 예외는 무엇입니까 ?? 이것은 엉망입니다. – OldProgrammer

+0

커서 for 루프 다음에 다른 코드가 있고 다른 블록이 그 예외 일 때 예외가 있습니다. –

+2

그래서 예외는 무엇입니까 ??? 모든 관련 정보를 제공 할 수 없다면 어떻게 누군가가 당신을 도울 것으로 기대합니까? – OldProgrammer

답변

1

업데이트이 사항이 시나리오에서 작동에 대한 열린 커서 수행 할 때 : 첫 번째 실행 선택 쿼리에서와 모든 레코드에 대한을 고정하고 후 작업을 가져 할 설정합니다.

PROCEDURE test(p_id IN NUMBER) 
IS 

    CURSOR cur_test IS 
    SELECT emp_id, 
     emp_name, 
     rowid as row_id 
    FROM 
     EMP; 

    row_locked EXCEPTION; 
    PRAGMA EXCEPTION_INIT(row_locked, -54); 

    v_sql varchar2(4000) := 'SELECT 1 FROM EMP t WHERE rowid = :row_id FOR UPDATE NOWAIT'; 
    c int; 
    n int; 
BEGIN 
    c := dbms_sql.open_cursor; 
    dbms_sql.parse(c, v_sql, dbms_sql.native); 

    FOR r_cur_test IN cur_test 
    LOOP 
    BEGIN 
     dbms_sql.bind_variable (c, 'row_id', i.row_id); 
     n := dbms_sql.execute(c); 

     --do something 

    EXCEPTION 
     WHEN row_locked THEN 
     --log locked record in log table 
     log_lock('Record is locked'); 
     COMMIT; 
    END;  
    END LOOP; 

    dbms_sql.close_cursor(c); 

    --call log function to log a successful run 

    COMMIT; 
EXCEPTION 
    WHEN OTHERS THEN 
    --Unsuccessful completion of the run.Trap all unhandled exceptions. 
    --log error in error table  
    log_lock('Process exited with error'); 
    dbms_sql.close_cursor(c); 
    ROLLBACK; 

END; 
+0

상세한 답변을 많이 주셔서 감사합니다. –