CODE INSIDE

Writing loops in T-SQL

The topic is quite old, but I found it really helpful, so be warned.

Scenario: Iterate over a result set and insert it in a new table in T-SQL

I had to write a SQL migration script to move date from an old table into a new table with a new primary key.

Update! I discovered that my problem would have been solved with a much simpler SQL script (INSERT INTO x …(SELECT … FROM Y)). So my example here is pretty dumb - sorry if this confuses you, but I will keep the blogpost to show the mechanics. Thanks Mark!

Here was/is my resulting script using T-SQL Cursors:

DECLARE @TemplateId as uniqueidentifier;
DECLARE @UserId as uniqueidentifier;

DECLARE @OldTemplateFavCursor as CURSOR;

SET @OldTemplateFavCursor = CURSOR FOR
SELECT UserTemplate.[Template_Id], UserTemplate.[User_Id] FROM UserTemplate;
 
OPEN @OldTemplateFavCursor;
FETCH NEXT FROM @OldTemplateFavCursor INTO @TemplateId, @UserId;
 
WHILE @@FETCH_STATUS = 0
BEGIN
 INSERT INTO dbo.[UserFavoriteTemplate]
           ([Id]
           ,[TemplateId]
           ,[UserId])
     VALUES
           (NEWID()
           ,@TemplateId
           ,@UserId)

FETCH NEXT FROM @OldTemplateFavCursor INTO @TemplateId, @UserId;
END
 
CLOSE @OldTemplateFavCursor;
DEALLOCATE @OldTemplateFavCursor;

Explanation

In the first couple of lines we just declare some variables.

In this particular script we want to move the “TemplateId” & “UserId” from the table “UserTemplate” into the target table “UserFavoriteTemplate”, but I also want to store an additional GUID as Id.

This line will select our current data into the cursor:

SET @OldTemplateFavCursor = CURSOR FOR SELECT UserTemplate.[Template_Id], UserTemplate.[User_Id] FROM UserTemplate;

With the “OPEN”, “FETCH NEXT” and “CLOSE” we move the cursor and inside the “WHILE” we can do our migration.

The syntax seems (from a C# perspective) strange, but works well for this scenario.

Performance consideration

I wouldn’t recommend this approach for large scale migrations or actual production code because I heard that the performance is not as great as some clever joins or other T-SQL magic.

Make sure you really need this

You can do some clever joins with SQL - make sure you really need this approach. My example here is not a clever one, so use this feature wisely. (again - thanks to Mark for the comment!)

Thanks Christopher for your help!

blog comments powered by Disqus