i want to generate a unique number from a table.
It has to be thread safe of course, so when i check for the last number and get ‘3’, and then store ‘4’ in the database, i don’t want anybody else just in between those two actions (get the number and store it one higher in the database) also to get ‘3’ back, and then also storing ‘4’
So i thought, put it in a transaction like this:
begin transaction
declare @maxNum int
select @maxNum = MAX(SequenceNumber) from invoice
where YEAR = @year
if @maxNum is null
begin
set @maxNum = 0
end
set @maxNum = @maxNum + 1
INSERT INTO [Invoice]
([Year]
,[SequenceNumber]
,[DateCreated])
VALUES
(@year
,@maxNum
,GETUTCDATE()
)
commit transaction
return @maxNum
But i wondered, is that enough, to put it in a transaction?
my first thought was: it locks this sp for usage by other people, but is that correct? how can sql server know what to lock at the first step?
Will this construction guarantee me that nobody else will do the select @maxnum part just when i am updating the @maxnum value, and at that moment receiving the same @maxnum as i did so i’m in trouble.
I hope you understand what i want to accomplish, and also if you know if i did choose the right solution.
EDIT:
also described as ‘How to Single-Thread a stored procedure’
As it turned out, i didn’t want to lock the table, i just wanted to execute the stored procedure one at a time.
In C# code i would place a lock on another object, and that’s what was discussed here
http://www.sqlservercentral.com/Forums/Topic357663-8-1.aspx
So that’s what i used
where ‘holdit1’ is just a name for the lock.
@resultreturns 0 or 1 if it succeeds in getting the lock (one of them is when it immediately succeeds, and the other is when you get the lock while waiting)