【问题标题】:SQL Server Option tag usageSQL Server 选项标记用法
【发布时间】:2015-12-23 18:27:39
【问题描述】:

我有以下功能。

ALTER FUNCTION [dbo].[fnSplit] (@s VARCHAR(8000))
RETURNS table
AS
RETURN (
    WITH Pieces(start, stop) AS (
      SELECT 1, CHARINDEX(',', @s)
      UNION ALL
      SELECT stop + 1, CHARINDEX(',', @s, stop + 1)
      FROM Pieces
      WHERE stop > 0
    )
    SELECT SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 8000 END) AS s
    FROM Pieces
  )

如果我使用非常长的字符串运行此函数,我会收到错误“在语句完成之前,最大递归 100 已用尽”。我无法应用“选项(maxrecursion 0)”,因为它给了我错误说“选项附近的语法错误”。

谁能告诉我这是什么问题?

提前致谢。

【问题讨论】:

  • 使用loop/tally table/xml+cross申请拆分。无需使用递归 cte demo
  • @lad2025 是对的。不过,您如何使用option
  • 我无法使用“选项(maxrecursion 0)”。
  • 我知道你遇到了错误,所以我才问你是如何使用它的。

标签: sql sql-server


【解决方案1】:

您不能将OPTION 子句添加到函数定义中。但是你可以在调用函数的时候使用它。

此示例使用以下 UDF,并带有递归 CTE。

CREATE FUNCTION dbo.fnTEST (@Limit INT)
RETURNS TABLE
AS
RETURN
    (
        /* Returns a table counting 1 to @Limit
         * using recursion.
         */
        WITH x AS
            (
                    SELECT
                        1 AS n

                UNION ALL

                    SELECT
                        n + 1
                    FROM 
                        x
                    WHERE
                        n < @Limit
            )
        SELECT
            *
        FROM
            x    
    )
GO

任何超过 100 的 @Limit 都会返回错误,除非您在调用语句中包含 MAXRECURSION 表提示。

如何打电话

SELECT
    *
FROM
    dbo.fnTEST(105)
OPTION
    (MAXRECURSION 200)        
;

编辑:正如其他人指出的那样,有更有效的解决方案来解决这个问题。在这种情况下,重构代码可能会更好,请参阅 OP 中 @Lad2025 的评论,其中包括一个方便的演示。

编辑 2:@Devart 发布了一个答案,表明您可以包含 OPTION 子句,如果您首先在 VAR 中构建表然后返回它。

【讨论】:

    【解决方案2】:
    CREATE FUNCTION dbo.fnSplit
    (
        @s VARCHAR(8000)
    )
    RETURNS @ret TABLE (val NVARCHAR(4000))
    AS BEGIN
    
        ;WITH Pieces(start, [stop]) AS (
          SELECT 1, CHARINDEX(',', @s)
          UNION ALL
          SELECT [stop] + 1, CHARINDEX(',', @s, [stop] + 1)
          FROM Pieces
          WHERE [stop] > 0
        )
        INSERT INTO @ret (val)
        SELECT SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 8000 END) AS s
        FROM Pieces
        OPTION(MAXRECURSION 0)
    
        RETURN
    
    END
    GO
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      • 1970-01-01
      • 2014-08-28
      • 2016-01-04
      • 1970-01-01
      • 2018-10-30
      • 2011-02-16
      相关资源
      最近更新 更多