Поведението, което сте срещнали за ЗА АКТУАЛИЗАЦИЯ SKIP LOCKED, е описано в тази бележка в блога. Моето разбиране е, че клаузата FOR UPDATE се оценява СЛЕД клаузата WHERE. SKIP LOCKED е като допълнителен филтър, който гарантира, че сред редовете, които биха били върнати, нито един не е заключен.
Вашето изявление е логически еквивалентно на:намерете първия ред от card_numbers
и го върнете, ако не е заключен. Очевидно това не е това, което искате.
Ето малък тестов случай, който възпроизвежда поведението, което описвате:
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
----------
От втория избор не се връща ред. Можете да използвате курсора, за да заобиколите този проблем:
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
Тъй като изрично извадих курсора, ще бъде върнат само един ред (и само един ред ще бъде заключен).