sql >> Base de Datos >  >> RDS >> Oracle

Selección de Oracle para el comportamiento de actualización

El comportamiento que ha encontrado para FOR UPDATE SKIP LOCKED se ha descrito en esta nota de blog. Tengo entendido que la cláusula FOR UPDATE se evalúa DESPUÉS de la cláusula WHERE. El SKIP LOCKED es como un filtro adicional que garantiza que entre las filas que se habrían devuelto, ninguna esté bloqueada.

Su declaración es lógicamente equivalente a:encuentre la primera fila de card_numbers y devolverlo si no está bloqueado. Obviamente esto no es lo que quieres.

Aquí hay un pequeño caso de prueba que reproduce el comportamiento que describe:

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
----------

No se devuelve ninguna fila de la segunda selección. Puede usar un cursor para solucionar este 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

Dado que busqué explícitamente el cursor, solo se devolverá una fila (y solo se bloqueará una fila).