1

I know I should try to avoid while loop in sql but I could not get it done, can someone please suggest a better way to achieve same result without using while loop. Here is my code -

begin transaction

declare @count int;
set @count = 1;

declare @Id bigint;
set @Id = 3781543256;

while @count <=35000

begin

INSERT INTO [Table_name]
           ([Column1]
           ,[Column2]
           ,[Column3]
           ,[Column4]
           ,[Column5])
     VALUES
           (7,
           @Id,
           '20130909 16:42:43.157',
           0,
           NEWID())

set @Id = @Id+1; 

set @count = @count+1;
end
7
  • 1
    Basically - the avoidance of "loop" in SQL is if something needs to run/query often and perform well. If it is something you run rarely or "once in a while to set up data", it is okay to have loops - and in this case, I hope it's not something you'll need to run often, so why not just keep the loop? Commented Jun 25, 2014 at 9:06
  • @Jesuraja I have edited my question, actually -@nodeID is Id. Commented Jun 25, 2014 at 9:09
  • 5 Columns and 7 Values? Commented Jun 25, 2014 at 9:13
  • @user3581461 The proposed edit was rejected by 3 auditers so it didn't go through. I went in an re-added your changes. Can you verify that I did not mess it up? Commented Jun 25, 2014 at 9:40
  • @ivarni Can you please confirm which changes you wanted in it? Commented Jun 26, 2014 at 7:34

3 Answers 3

3

You need a numbers table. It is handy to have around anyway. Assuming you have it, you can generate the set of rows you want to insert and do it in one go:

INSERT ...
SELECT 7, Numbers.ID - 1 + 3781543256, ..., NEWID()
FROM Numbers
WHERE Numbers.ID BETWEEN 1 AND @count

Shorter, less error prone and faster. Depending on the row count and schema this can be faster by multiple orders of magnitude.

Sign up to request clarification or add additional context in comments.

Comments

1
INSERT INTO [Table_name] (
    [Column1]
   ,[Column2]
   ,[Column3]
   ,[Column4]
   ,[Column5]
)
SELECT TOP 35000
       7
      ,@Id + ROW_NUMBER() OVER (ORDER BY objects1.object_id)
      ,'20130909 16:42:43.157'
      ,0
      ,NEWID()
FROM sys.objects AS objects1
     CROSS JOIN sys.objects AS objects2

2 Comments

Just out of interest: what is the CROSS JOIN for?
@MP24, just an ansi version of a comma in this case (i.e. cartesian product). I just think it is more readable to explicitly say CROSS JOIN. Or did you mean why it is there at all? sys.objects usually contains a couple of thousand rows. The CROSS join ensures we get at least 37000 rows
0

Here is an example using a recursive cte to get a list of 35000 rows...

WITH cte1 AS 
(
    SELECT 1 AS id
    UNION ALL SELECT id + 1 FROM cte1
    WHERE id < 1000 
),
cte2 AS 
(
    SELECT id FROM cte1 
    UNION ALL
    SELECT id + 1000 FROM cte2
    WHERE cte2.id <= 34000 --(the number of rows you want - 1000)
)
INSERT INTO [Table_name]
           ([Column1]
           ,[Column2]
           ,[Column3]
           ,[Column4]
           ,[Column5]
           ,[Column6]
           ,[Column7]
           ,[Column8])
SELECT
    7,
    @id + id,
    1.1,
    0,
    '20130909 16:42:43.157',
    '20130910 16:42:43.157',
    0,
    NEWID()
FROM cte2 
ORDER BY id
OPTION (MAXRECURSION 1000)

Note - split into 2 CTES as you can only have a maximum recursion limit of 32767 in a single cte. The default recursion limit is 100 - hence the OPTION (MAXRECURSION 1000)

I've done a quick test of the SELECT part of this, and it is very fast - less than a second.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.