This will work, but also completely blocks all access to the table.
If you do WITH(UPDLOCK, HOLDLOCK) , you can block a lower level of detail (than a table) and a mode (than an exclusive).
HOLDLOCK gives serializable semantics, so you can simply lock the range at the top of the index (if you have one on LocName,InvNumber ).
UPDLOCK ensures that two simultaneous transactions cannot contain the same lock, but, unlike the exclusive one, they do not block other (normal) readers that do not use the prompt.
BEGIN TRANSACTION DECLARE @i INT SELECT @i = MAX(InvNumber) FROM Invoice WITH(UPDLOCK, HOLDLOCK) WHERE LocName = 'A' WAITFOR delay '00:00:10' SET @ i=@i + 1 INSERT INTO Invoice VALUES ('A', @i); COMMIT
Alternatively, you can simply use sp_getapplock to serialize access to this code.
source share