Reputation: 156
I have create an sql procedure in my oracle database that I will call later on on my c# code,
the main goal of this procedure is to loop over entries and make some treatment in a condition that every entry should be treated only once.
The body of the procedure looks like that.
FOR item IN
( SELECT * FROM
(SELECT tab1.item1,tab1.item2,tab1.item3...
FROM tab1
INNER JOIN tab2 ON ...condition...
INNER JOIN TAB3 ON ...condition...
WHERE ....main_condition=true;
ORDER BY tab1.item1
)
WHERE ROWNUM < in_param
)
LOOP
.
.
.
dbms_lock.sleep(4);
.
.
.
"set main_condition=false;"
commit;
END LOOP;
What can I do in a way that when two user call this procedure at the same time, they get a different set of rows.
thank you.
Upvotes: 1
Views: 230
Reputation: 146329
"a condition that every entry should be treated only once."
That sounds like a queue. The usual way of managing that would be to implement the queue with a SELECT … FOR UPDATE SKIP LOCKED cursor. There is a very important caveat here: that the treatment you refer to in your question include something which affects the initial criteria, say by updating a status value or deleting an identifying record (or whatever - unfortunately, questions which are vague about their specifics can only attract equally vague answers).
So it might lock something like this (obviously indicative code):
cursor c_whatever is
SELECT tab1.item1,tab1.item2,tab1.item3...
FROM tab1
INNER JOIN tab2 ON ...condition...
INNER JOIN TAB3 ON ...condition...
WHERE tab1.main_condition = true
FOR UPDATE OF tab1.main_condition SKIP LOCKED ;
begin
open c_whatever;
….
update tab1
set tab1.main_condition = false
where tab1.item1 = ….
commit;
Pessimistic locking will prevent two sessions grabbing the same row. Updating the columns which feed WHERE clause will prevent the same record being treated more than once.
Upvotes: 2
Reputation: 9886
What can I do in a way that when two user call this procedure at the same time, they get a different set of rows.
You can modify your query and use ORDER BY DBMS_RANDOM.VALUE
to get random rows. Hence you can modify your query as
SELECT * FROM
(SELECT tab1.item1,tab1.item2,tab1.item3...
FROM tab1
INNER JOIN tab2 ON ...condition...
INNER JOIN TAB3 ON ...condition...
WHERE ....main_condition=true;
ORDER BY DBMS_RANDOM.VALUE
Upvotes: 1