生成一定长度的结果集

时间:2014-01-17 18:21:31

标签: tsql sql-server-2012

我需要在某些表中插入一定数量的行,并从变量中获取值。我当然可以一次插入一行循环,但这太简单了。我正在寻找更优雅的解决方案。我目前的想法是围绕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,这对我来说不合适。你能建议替代方案吗?

2 个答案:

答案 0 :(得分:3)

  1. 在创建或引用对象时始终使用dbo.架构前缀,尤其是函数。
  2. 如果可能,您应该努力创建内联表值函数,而不是多语句表值函数。
  3. 递归CTE是生成集合的最低效方法(更好的示例见这个由三部分组成的系列):

  4. 以下是一个例子:

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

不要反复思考 - 循环 - 但是基于集合 - 一次性完成。

INSERT INTO ... SELECT TOP x ...应该做你需要的而不重复插入。

当我没有绑定到手机时,我会跟着一个例子。

更新:

@AaronBertrand说的是什么。 :} CROSS JOIN中的SELECT是正确的。