Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle seleciona para comportamento de atualização


O comportamento que você encontrou para FOR UPDATE SKIP LOCKED foi descrito nesta nota do blog. Meu entendimento é que a cláusula FOR UPDATE é avaliada AFTER a cláusula WHERE. O SKIP LOCKED é como um filtro adicional que garante que entre as linhas que seriam retornadas, nenhuma seja bloqueada.

Sua declaração é logicamente equivalente a:encontre a primeira linha de card_numbers e devolva-o se não estiver bloqueado. Obviamente não é isso que você quer.

Aqui está um pequeno caso de teste que reproduz o comportamento que você descreve:
SQL> CREATE TABLE t (ID PRIMARY KEY)
  2  AS SELECT ROWNUM FROM dual CONNECT BY LEVEL <= 1000;

Table created

SESSION1> select id from t where rownum <= 1 for update skip locked;

        ID
----------
         1

SESSION2> select id from t where rownum <= 1 for update skip locked;

        ID
----------

Nenhuma linha é retornada da segunda seleção. Você pode usar um cursor para contornar esse problema:
SQL> CREATE FUNCTION get_and_lock RETURN NUMBER IS
  2     CURSOR c IS SELECT ID FROM t FOR UPDATE SKIP LOCKED;
  3     l_id NUMBER;
  4  BEGIN
  5     OPEN c;
  6     FETCH c INTO l_id;
  7     CLOSE c;
  8     RETURN l_id;
  9  END;
 10  /

Function created

SESSION1> variable x number;
SESSION1> exec :x := get_and_lock;

PL/SQL procedure successfully completed
x
---------
1

SESSION2> variable x number;
SESSION2> exec :x := get_and_lock;

PL/SQL procedure successfully completed
x
---------
2

Como eu busquei explicitamente o cursor, apenas uma linha será retornada (e apenas uma linha será bloqueada).