2016-09-20 94 views
0

我必須將特定數量的行插入到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天。

我該如何在沒有任何循環或多重插入語句的單個語句中執行此操作?

+0

很明顯,你正在嘗試創建一個運行數字/日期列表:[在我的答案之一](http://stackoverflow.com/a/32474751/5089204),你會發現一個使用「Tally-CTE」爲每一天創建一個數字,日期和許多附帶信息的列表。認爲這是你需要的... – Shnugo

回答

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行,結果

+0

這是最快和最可行的解決方案,謝謝。 –

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(@[email protected] +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 
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,這意味着無界限,但是隻能在測試代碼後執行此操作,因爲它可能會以這種方式陷入無限循環(這就是默認情況下存在限制的原因)。

+0

這種*現代的,基於集合的方式*比'CROSS JOIN'方法慢大約3-5倍。遞歸CTE是一個隱藏的RBAR。他們很好地擺弄一棵樹,但不是創建跑步列表的最佳工具... – Shnugo

+0

@Shnugo你去了,刪除了多餘的形容詞 – knuckles

相關問題