Hi,Im trying to lock a table for the duration of a transaction. When I say lock, I dont just mean to stop insert and updates, but I also dont want anything to select from the table either.The code is being run inside a trigger, which is shown below:ALTER TRIGGER TR_UpdateTable_SetGlobalNumber ON dbo.UpdatesINSTEAD OF INSERTAS BEGIN DECLARE insertedItems CURSOR FAST_FORWARD FOR SELECT TableId,ColumnsChanged,RowGuidValue,Operation,UpdateId,ShadowId FROM inserted DECLARE @tableId uniqueidentifier DECLARE @columnsChanged varbinary(15) DECLARE @operation tinyint DECLARE @idValue uniqueidentifier DECLARE @updateId uniqueidentifier DECLARE @numInInserted bigint DECLARE @offset bigint DECLARE @nextNum bigint DECLARE @nextIncrement bigint DECLARE @globalUpdateNumber bigint DECLARE @shadowId uniqueidentifier DECLARE @doIncrement tinyint OPEN insertedItems SET @numInInserted = @@CURSOR_ROWS -- within this transaction I dont want the GlobalUpdateNumber -- table to be available to any other calls BEGIN TRANSACTION SELECT @globalUpdateNumber=UpdateNumber,@nextIncrement=UpdateIncrement FROM GlobalUpdateNumber IF ( 9223372036854775800 - @globalUpdateNumber < @numInInserted ) BEGIN SET @doIncrement = 1 SET @offset = @numInInserted - (9223372036854775800 - @globalUpdateNumber) UPDATE GlobalUpdateNumber SET UpdateNumber = @offset, UpdateIncrement=UpdateIncrement+1 SET @nextNum = 9223372036854775800-@numInInserted+@offset END ELSE BEGIN SET @doIncrement = 0 UPDATE GlobalUpdateNumber SET UpdateNumber = @globalUpdateNumber + @numInInserted SET @nextNum = @globalUpdateNumber END COMMIT FETCH NEXT FROM insertedItems INTO @tableId,@columnsChanged,@idValue,@operation,@updateId,@shadowId WHILE @@FETCH_STATUS = 0 BEGIN INSERT INTO Updates (TableId,ColumnsChanged,RowGuidValue,Operation,GlobalChangeNumber,GCNIncrement,UpdateId,ShadowId) VALUES (@tableId,@columnsChanged,@idValue,@operation,@nextNum,@nextIncrement,@updateId,@shadowId) IF ( @doIncrement = 1 AND @nextNum > 9223372036854775800 ) BEGIN SET @nextNum = 0 SET @nextIncrement = @nextIncrement + 1 END ELSE SET @nextNum = @nextNum + 1 FETCH NEXT FROM insertedItems INTO @tableId,@columnsChanged,@idValue,@operation,@updateId,@shadowId END CLOSE insertedItems DEALLOCATE insertedItemsEND
The problem with the above was that when more than 1 item was being inserted at basically the same time, both would get the same number. So if "A" & "B" inserted at the same time, "A" would get 10 from the globalupdate number table, and then "B" would do the same before "A" could update the number to 11. Hence "A" and "B" would have 10 as their number, instead of "A"=10 and "B"=11.I had a look for ways to lock a table, but was unable to find a solution which would solve this problem. I cant use ISOLATION LEVEL on the transaction, because that only stops inserts and updates. I also tried creating a function which returned a table (which I could lock in the select statement), however I cant update a table inside the function, which kind of defeated the purpose.