2016-11-28 10 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; 

、Iは、セッション1を開き、

select * from EMP FOR UPDATE NOWAIT 

を実行し、セッション2で、私はそれが常に結果として、OTHERS例外に行っ

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

詳細な答えをありがとう。 –

関連する問題