如何根据一系列数字

时间:2016-09-20 13:35:53

标签: sql-server sql-server-2008

我必须在SQL Server表中插入特定数量的行。

DECLARE @val AS INT = 20, 
        @val2 AS VARCHAR(50), 
        @Date AS DATETIME = CONVERT(DATETIME,'02-05-2016'),
        @i AS INT = 0

SET @val2 = 'abc'

DECLARE @tbl TABLE
(
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [val2] VARCHAR(50) NULL,
    [datum] [datetime] NULL
)

--INSERT INTO @tbl
SELECT @val2, DATEADD(DAY, @i, @Date)
UNION ALL
SELECT @val2, DATEADD(DAY, @i, @Date)

在这个查询中,我必须插入从给定日期开始的日期,直到分配给变量'@val'的值的数量。因此,在这种情况下,需要从'02 -05-2016'开始向表中插入20行,然后每行增加1天。

如何在没有任何循环或多个插入语句的单个语句中执行此操作?

3 个答案:

答案 0 :(得分:1)

如果你有一个数字表,你可以使用数字表,如果你想要一个值为2048的数字表,你可以使用master.dbo.spt_values,或者创建一个你自己的数字表。在这种情况下,您可以使用master.dbo.spt_values

DECLARE @val AS INT=20, @val2 AS VARCHAR(50);
DECLARE @Date AS DATETIME = CONVERT(DATETIME,'02-05-2016');

SET @val2 = 'abc'

INSERT INTO dbo.YourTable
SELECT @val2, DATEADD(DAY,number,@Date)
FROM master.dbo.spt_values
WHERE type = 'P'
AND number <= @val;

虽然从零开始,但结果会得到21行

答案 1 :(得分:0)

除了我在评论中指出的详细答案外,简而言之就是这个想法:

DECLARE @start INT=0;
DECLARE @end INT=19; --0 to 19 are 20 days

DECLARE @StartDate DATE={d'2016-01-01'};

--Create a List of up to 1.000.000.000 rows on the fly
--This is limited by start and end parameter

;WITH x AS(SELECT 1 AS N FROM(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS tbl(N))--10^1
,N3 AS (SELECT 1 AS N FROM x CROSS JOIN x AS N2 CROSS JOIN x N3) --10^3
,Tally AS(SELECT TOP(@end-@start +1) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) + @start -1 AS Nr FROM N3 
          CROSS JOIN N3 N6 CROSS JOIN N3 AS N9)

--INSERT INTO your_table

SELECT @val2 --your @val2 here as a constant value
      ,DATEADD(DAY,Nr,@StartDate)
FROM Tally

答案 2 :(得分:0)

您可以使用recursive CTE

DECLARE @i INT = 1
    , @m INT = 19
    , @d DATETIME2 = '2016-05-02';

WITH i AS (
    SELECT 0 AS increment
    UNION ALL
    SELECT i.increment + @i
    FROM i
    WHERE i.increment < @m
)
SELECT i.increment
    , DATEADD(DAY, i.increment, @d)
FROM i
OPTION (MAXRECURSION 100);

请注意底部的OPTION (MAXRECUSION 100)提示,这不是绝对必要的,但我已将其包含在内以说明其工作原理。默认情况下,使用此方法的结果限制为100,因此如果没有此语句,并且@m数量很大,例如1000然后SQL会生成错误。您可以将lmit设置为0,这意味着无限制,但只能在测试代码后执行此操作,因为它可能会以这种方式陷入无限循环(这就是默认情况下存在限制的原因)。