Den adfærd, du er stødt på for FOR OPDATERING SKIP OVER LÅST, er blevet beskrevet i denne blognote. Min forståelse er, at FOR UPDATE-klausulen evalueres EFTER WHERE-klausulen. SKIP LOCKED er som et ekstra filter, der garanterer, at ingen blandt de rækker, der ville være blevet returneret, er låst.
Dit udsagn svarer logisk til:find den første række fra card_numbers
og returner den, hvis den ikke er låst. Det er åbenbart ikke, hvad du ønsker.
Her er en lille testcase, der gengiver den adfærd, du beskriver:
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
----------
Ingen række returneres fra det andet valg. Du kan bruge en markør til at omgå dette problem:
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 jeg eksplicit har hentet markøren, vil kun én række blive returneret (og kun én række vil blive låst).