Reputation: 76464
I have a very interesting problem.
I have a table where I have data, like this: DVDSerialNumbers(ID, Create_Date, SerialNumber, CategoryID)
My application generates serial numbers for DVD's and I have a SQL command like this (issued by my application):
ExecuteQuery("select top {0} SerialNumber from DVDSerialNumbers where CategoryID = {1};" &
"delete from DVDSerialNumbers where ID in (select top{0} ID from DVDSerialNumber where " &
"CategoryID = {1});", n, CategoryID)
ExecuteQuery returns the result of my select query but the delete command is executed too.
Basically I get no more than n SerialNumbers which have the given CategoryID and I delete their rows.
However, here I have a concurency problem. If the code above runs twice in the same time, it's possible that the results will be the same, however, the idea is to get a given SerialNumber from the table only once.
How can I make instance B to wait for instance A to finish this command? Should I lock the table? Or should I lock some rows? Or is there a better solution?
Thanks in advance for your help.
Upvotes: 4
Views: 3022
Reputation: 432261
You need READPAST, UPDLOCK, ROWLOCK hints. See this for more: SQL Server Process Queue Race Condition
Then you'd need a transaction for the SELECT/DELETE. Instead, you can do this in one statement with an OUTPUT clause
ExecuteQuery("delete top ({0})
DVDSerialNumbers WITH (READPAST, UPDLOCK, ROWLOCK)
OUTPUT DELETED.SerialNumber
where CategoryID = {1}" &
, n, CategoryID)
Upvotes: 3