Oracle
 sql >> Database >  >> RDS >> Oracle

Oracle seleziona per il comportamento di aggiornamento

Il comportamento che hai riscontrato per FOR UPDATE SKIP LOCKED è stato descritto in questa nota del blog. La mia comprensione è che la clausola FOR UPDATE viene valutata DOPO la clausola WHERE. Lo SKIP LOCKED è come un filtro aggiuntivo che garantisce che tra le righe che sarebbero state restituite, nessuna sia bloccata.

La tua affermazione è logicamente equivalente a:trova la prima riga da card_numbers e restituirlo se non è bloccato. Ovviamente questo non è quello che vuoi.

Ecco un piccolo test case che riproduce il comportamento che descrivi:

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

Nessuna riga viene restituita dalla seconda selezione. Puoi utilizzare un cursore per aggirare questo 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

Dato che ho richiamato esplicitamente il cursore, verrà restituita solo una riga (e solo una riga verrà bloccata).