What is wrong with the T-SQL below that a colleague of mine wrote?
DECLARE @newId int,@counter int,@oldId int,@id int
SET @oldId=0
SET @counter=0
DECLARE ScheduleStep_Cursor CURSOR FOR
SELECT [id],[scheduleId] FROM [ScheduleStep] order by scheduleId asc
OPEN ScheduleStep_Cursor;
FETCH NEXT FROM ScheduleStep_Cursor INTO @id,@newId
WHILE @@FETCH_STATUS = 0
BEGIN
print 'Schedule : ' + convert(varchar, @newId) + ' id : ' + convert(varchar, @id)
IF (@oldId=null OR @oldId=0)
BEGIN
SET @counter=1
UPDATE
[ScheduleStep]
SET
milestoneCount=@counter
WHERE
[id]=@id
END
ELSE IF(@oldId=@newId)
BEGIN
SET @counter=@counter+1
UPDATE
[ScheduleStep]
SET
milestoneCount=@counter
WHERE
[id]=@id
END
ELSE
BEGIN
SET @counter=1
UPDATE
[ScheduleStep]
SET
milestoneCount=@counter
WHERE
[id]=@id
END
SET @oldId=@newId
FETCH NEXT FROM ScheduleStep_Cursor INTO @id,@newId
END
CLOSE ScheduleStep_Cursor;
DEALLOCATE ScheduleStep_Cursor;
The problem is that whilst looping round the cursor, the same rows that are being looped round are being updated, which can result in all kinds of weirdness including an infinite loop. The solution is to make use of the INSENSITIVE keyword which means that the data to be used by the cursor is copied to a temporary table in tempdb. You can then freely update the original table without any problems.
DECLARE ScheduleStep_Cursor INSENSITIVE CURSOR FOR
SELECT [id],[scheduleId] FROM [ScheduleStep] order by scheduleId asc