如何避免在Sql中循环

时间:2014-06-25 09:01:12

标签: sql sql-server sql-server-2008

我知道我应该尽量避免在sql中循环,但我无法完成它,有人可以建议一个更好的方法来实现相同的结果而不使用while循环。这是我的代码 -

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

3 个答案:

答案 0 :(得分:3)

你需要一个数字表。无论如何都要方便。假设您拥有它,您可以生成要插入的行集并一次性执行:

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

更短,更不容易出错且速度更快。根据行数和架构,这可以更快几个数量级。

答案 1 :(得分: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 :(得分:0)

以下是使用递归cte获取35000行列表的示例...

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)

注意 - 拆分为2个CTES,因为在单个cte中只能有32767的最大递归限制。默认递归限制为100 - 因此OPTION (MAXRECURSION 1000)

我已对SELECT部分​​进行了快速测试,速度非常快 - 不到一秒钟。