Is there a way to loop through a table variable in TSQL without using a cursor?
First of all you should be absolutely sure you need to iterate through each row — set based operations will perform faster in every case I can think of and will normally use simpler code.
Depending on your data it may be possible to loop using just SELECT
statements as shown below:
Declare @Id intWhile (Select Count(*) From ATable Where Processed = 0) > 0Begin Select Top 1 @Id = Id From ATable Where Processed = 0 --Do some processing here Update ATable Set Processed = 1 Where Id = @Id End
Another alternative is to use a temporary table:
Select *Into #TempFrom ATableDeclare @Id intWhile (Select Count(*) From #Temp) > 0Begin Select Top 1 @Id = Id From #Temp --Do some processing here Delete #Temp Where Id = @IdEnd
The option you should choose really depends on the structure and volume of your data.
Note: If you are using SQL Server you would be better served using:
WHILE EXISTS(SELECT * FROM #Temp)
Using COUNT
will have to touch every single row in the table, the EXISTS
only needs to touch the first one (see Josef's answer below).
Just a quick note, if you are using SQL Server (2008 and above), the examples that have:
While (Select Count(*) From #Temp) > 0
Would be better served with
While EXISTS(SELECT * From #Temp)
The Count will have to touch every single row in the table, the EXISTS
only needs to touch the first one.
This is how I do it:
declare @RowNum int, @CustId nchar(5), @Name1 nchar(25)select @CustId=MAX(USERID) FROM UserIDs --start with the highest IDSelect @RowNum = Count(*) From UserIDs --get total number of recordsWHILE @RowNum > 0 --loop until no more recordsBEGIN select @Name1 = username1 from UserIDs where USERID= @CustID --get other info from that row print cast(@RowNum as char(12)) + ' ' + @CustId + ' ' + @Name1 --do whatever select top 1 @CustId=USERID from UserIDs where USERID < @CustID order by USERID desc--get the next one set @RowNum = @RowNum - 1 --decrease countEND
No Cursors, no temporary tables, no extra columns.The USERID column must be a unique integer, as most Primary Keys are.