2014-01-17 137 views
1

我需要在某些表中插入一定數量的行,並從變量中獲取值。我當然可以做一次循環插入單行,但這太簡單了。我正在尋找更優雅的解決方案。我目前的想法大約是INSERT INTO ... SELECT ...聲明,但現在我需要一個查詢來生成我需要的行數。我試着寫遞歸CTE做到這一點:生成一定長度的結果集

CREATE FUNCTION ufGenerateRows(@numRows INT = 1) 
RETURNS @RtnValue TABLE 
(
    RowID INT NOT NULL 
) 
AS 
BEGIN 
    WITH numbers AS 
    (
     SELECT 1 as N 
     UNION ALL 
     SELECT N + 1 
     FROM numbers 
     WHERE N + 1 <= @numRows 
    ) 
    INSERT INTO @RtnValue 
     SELECT N 
     FROM numbers 

    RETURN 
END 
GO 

它的工作原理,但有100遞歸深度,這是不適合我的極限。你能建議替代品嗎?

+1

可能重複的[SQL,輔助數字表](http://stackoverflow.com/questions/10819/sql-auxiliary-table-of-numbers) –

+0

您可以設置一個大於100的maxrecursion限制,但交叉加盟的CTE更好。 –

回答

3
  1. 創建或引用對象,尤其是功能時總是使用dbo.模式前綴。
  2. 如果可能,您應該努力創建內聯表值函數,而不是多語句表值函數。
  3. 遞歸的CTE是關於效率最低的方式來生成一組(參見更好的範例此三部分系列):

這裏是一個例子:

CREATE FUNCTION dbo.GenerateRows(@numRows INT = 1) 
RETURNS TABLE 
AS 
    RETURN 
    (
    SELECT TOP (@numRows) RowID = ROW_NUMBER() OVER (ORDER BY s1.[number]) 
     FROM master.dbo.spt_values AS s1 
     -- CROSS JOIN master.dbo.spt_values AS s2 
     ORDER BY s1.[number] 
); 

如果您需要超過2,500行,您可以與自身或其他表交叉連接。

更好的辦法是創建自己的數字表(再次請參閱上面的示例鏈接)。

1

不要反覆思考 - 循環 - 但基於集合 - 一次。

INSERT INTO ... SELECT TOPx ...應該做你需要的東西,而不重複插入。

我會跟着一個例子,當我不綁定到我的手機。

更新:

@AaronBertrand說什麼。 :} SELECT中的CROSS JOIN是點亮的。

+0

'SELECT'從什麼?爲了得到最頂層的'@ n'行,我需要一些已經有'@ n'行或更多行的行。 – n0rd