Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle-Auswahl für das Aktualisierungsverhalten

Das Verhalten, auf das Sie bei FOR UPDATE SKIP LOCKED gestoßen sind, wurde in diesem Blog-Hinweis beschrieben. Mein Verständnis ist, dass die FOR UPDATE-Klausel NACH der WHERE-Klausel ausgewertet wird. Das SKIP LOCKED ist wie ein zusätzlicher Filter, der garantiert, dass unter den Zeilen, die zurückgegeben worden wären, keine gesperrt sind.

Ihre Aussage ist logisch äquivalent zu:Finde die erste Zeile von card_numbers und zurückgeben, wenn es nicht verschlossen ist. Offensichtlich ist das nicht das, was Sie wollen.

Hier ist ein kleiner Testfall, der das von Ihnen beschriebene Verhalten reproduziert:

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

Von der zweiten Auswahl wird keine Zeile zurückgegeben. Sie können einen Cursor verwenden, um dieses Problem zu umgehen:

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

Da ich den Cursor explizit abgerufen habe, wird nur eine Zeile zurückgegeben (und nur eine Zeile wird gesperrt).