Funky
Funky

Reputation: 13602

How do I loop through a set of records in SQL Server?

How do I loop through a set of records from a select statement?

Say I have a few records that I wish to loop through and do something with each record. Here's a primitive version of my select statement:

select top 1000 * from dbo.table
where StatusID = 7

Upvotes: 221

Views: 785687

Answers (9)

江明哲
江明哲

Reputation: 37

I think this is the easy way example to iterate item.

You can change YOURTABLE or YOURCOLUMN to what you want.

declare @cateid int
select YOURCOLUMN into [#TempTable] from YOURTABLE

while (select count(*) from #TempTable) > 0
begin
    select top 1 @column = YOURCOLUMN from #TempTable
    print(@column)

    --DO SOMETHING HERE

    delete #TempTable where YOURCOLUMN = @column
end

drop table #TempTable

Upvotes: 0

Tom Warfield
Tom Warfield

Reputation: 776

Here is a small improvement to the top-voted answer from FloChanz: Use only ONE "FETCH" statement. That way it is easier to add a new column, and you avoid accidentally having the FETCH do two different things:

/*
create table my_table (yourfield varchar(100), statusid int)
insert into my_Table select 'abc', 7
insert into my_Table select 'pdq', 6
insert into my_Table select 'xyz', 7
*/
DECLARE @MyCursor CURSOR;
DECLARE @MyField varchar(100);
DECLARE @finished bit = 0
BEGIN
    SET @MyCursor = CURSOR FOR
    select top 1000 YourField from dbo.my_table
        where StatusID = 7

    OPEN @MyCursor
    while @finished = 0 begin
      FETCH NEXT FROM @MyCursor
      INTO @MyField
      if @@FETCH_STATUS = 0
      BEGIN
        /*
           YOUR ALGORITHM GOES HERE
        */
        print @MyField
      end else begin
        set @finished = 1
      END;
    END;

    CLOSE @MyCursor ;
    DEALLOCATE @MyCursor;
END;

Upvotes: 1

sam yi
sam yi

Reputation: 4934

This is what I've been doing if you need to do something iterative... but it would be wise to look for set operations first. Also, do not do this because you don't want to learn cursors.

select top 1000 TableID
into #ControlTable 
from dbo.table
where StatusID = 7

declare @TableID int

while exists (select * from #ControlTable)
begin

    select top 1 @TableID = TableID
    from #ControlTable
    order by TableID asc

    -- Do something with your TableID

    delete #ControlTable
    where TableID = @TableID

end

drop table #ControlTable

Upvotes: 157

Agnel Amodia
Agnel Amodia

Reputation: 769

By using cursor you can easily iterate through records individually and print records separately or as a single message including all the records.

DECLARE @CustomerID as INT;
declare @msg varchar(max)
DECLARE @BusinessCursor as CURSOR;

SET @BusinessCursor = CURSOR FOR
SELECT CustomerID FROM Customer WHERE CustomerID IN ('3908745','3911122','3911128','3911421')

OPEN @BusinessCursor;
    FETCH NEXT FROM @BusinessCursor INTO @CustomerID;
    WHILE @@FETCH_STATUS = 0
        BEGIN
            SET @msg = '{
              "CustomerID": "'+CONVERT(varchar(10), @CustomerID)+'",
              "Customer": {
                "LastName": "LastName-'+CONVERT(varchar(10), @CustomerID) +'",
                "FirstName": "FirstName-'+CONVERT(varchar(10), @CustomerID)+'",    
              }
            }|'
        print @msg
    FETCH NEXT FROM @BusinessCursor INTO @CustomerID;
END

Upvotes: 27

Precept
Precept

Reputation: 579

Small change to sam yi's answer (for better readability):

select top 1000 TableID
into #ControlTable 
from dbo.table
where StatusID = 7

declare @TableID int

while exists (select * from #ControlTable)
begin

    select @TableID = (select top 1 TableID
                       from #ControlTable
                       order by TableID asc)

    -- Do something with your TableID

    delete #ControlTable
    where TableID = @TableID

end

drop table #ControlTable

Upvotes: 49

Bunkerbuster
Bunkerbuster

Reputation: 1001

You could choose to rank your data and add a ROW_NUMBER and count down to zero while iterate your dataset.

-- Get your dataset and rank your dataset by adding a new row_number
SELECT  TOP 1000 A.*, ROW_NUMBER() OVER(ORDER BY A.ID DESC) AS ROW
INTO #TEMPTABLE 
FROM DBO.TABLE AS A
WHERE STATUSID = 7;

--Find the highest number to start with
DECLARE @COUNTER INT = (SELECT MAX(ROW) FROM #TEMPTABLE);
DECLARE @ROW INT;

-- Loop true your data until you hit 0
WHILE (@COUNTER != 0)
BEGIN

    SELECT @ROW = ROW
    FROM #TEMPTABLE
    WHERE ROW = @COUNTER
    ORDER BY ROW DESC

    --DO SOMTHING COOL  

    -- SET your counter to -1
    SET @COUNTER = @ROW -1
END

DROP TABLE #TEMPTABLE

Upvotes: 8

FloChanz
FloChanz

Reputation: 3429

By using T-SQL and cursors like this :

DECLARE @MyCursor CURSOR;
DECLARE @MyField YourFieldDataType;
BEGIN
    SET @MyCursor = CURSOR FOR
    select top 1000 YourField from dbo.table
        where StatusID = 7      

    OPEN @MyCursor 
    FETCH NEXT FROM @MyCursor 
    INTO @MyField

    WHILE @@FETCH_STATUS = 0
    BEGIN
      /*
         YOUR ALGORITHM GOES HERE   
      */
      FETCH NEXT FROM @MyCursor 
      INTO @MyField 
    END; 

    CLOSE @MyCursor ;
    DEALLOCATE @MyCursor;
END;

Upvotes: 294

Monojit Sarkar
Monojit Sarkar

Reputation: 2451

this way we can iterate into table data.

DECLARE @_MinJobID INT
DECLARE @_MaxJobID INT
CREATE  TABLE #Temp (JobID INT)

INSERT INTO #Temp SELECT * FROM DBO.STRINGTOTABLE(@JobID,',')
SELECT @_MinJID = MIN(JobID),@_MaxJID = MAX(JobID)  FROM #Temp

    WHILE @_MinJID <= @_MaxJID
    BEGIN

        INSERT INTO Mytable        
        (        
            JobID,        
        )        

        VALUES        
        (        
            @_MinJobID,        
        ) 

        SET @_MinJID = @_MinJID + 1;
    END

DROP TABLE #Temp

STRINGTOTABLE is user define function which will parse comma separated data and return table. thanks

Upvotes: 1

Sandeep
Sandeep

Reputation: 613

Just another approach if you are fine using temp tables.I have personally tested this and it will not cause any exception (even if temp table does not have any data.)

CREATE TABLE #TempTable
(
    ROWID int identity(1,1) primary key,
    HIERARCHY_ID_TO_UPDATE int,
)

--create some testing data
--INSERT INTO #TempTable VALUES(1)
--INSERT INTO #TempTable VALUES(2)
--INSERT INTO #TempTable VALUES(4)
--INSERT INTO #TempTable VALUES(6)
--INSERT INTO #TempTable VALUES(8)

DECLARE @MAXID INT, @Counter INT

SET @COUNTER = 1
SELECT @MAXID = COUNT(*) FROM #TempTable

WHILE (@COUNTER <= @MAXID)
BEGIN
    --DO THE PROCESSING HERE 
    SELECT @HIERARCHY_ID_TO_UPDATE = PT.HIERARCHY_ID_TO_UPDATE
    FROM #TempTable AS PT
    WHERE ROWID = @COUNTER

    SET @COUNTER = @COUNTER + 1
END


IF (OBJECT_ID('tempdb..#TempTable') IS NOT NULL)
BEGIN
    DROP TABLE #TempTable
END

Upvotes: 9

Related Questions