【问题标题】:Incorrect Syntax Near Keyword 'OPTION' in CTE StatementCTE 语句中关键字“OPTION”附近的语法不正确
【发布时间】:2014-08-03 00:16:33
【问题描述】:

尝试在 SQL Server 2008 中保存视图时,我收到“关键字'OPTION'附近的语法不正确”错误。我正在尝试将 MAXRECURSION 选项添加到公用表表达式的末尾。我见过的所有示例和我之前创建的工作 CTE 都不介意 CTE 末尾的“OPTION (MAXRECURSION 0)”。

有人知道我为什么会收到此错误吗? CTE 在没有 OPTION 子句的情况下工作,尽管它达到了最大递归数 (100)。

WITH CTE AS
(
  SELECT
    CDay,
    InvAcct,
    BuyerCode,
    PartNumber,
    ROP,
    ROP_ROQ,
    DailyDemand,
    StartingInvQty,
    SchedDeliveryQty,
    CAST(StartingInvQty - DailyDemand/2.0 AS decimal(18,4)) AS ProjInvQty
  FROM
    qryInventorySimulation
  WHERE
    MBC = 'B' AND
    CDay = CAST(CAST(GETDATE()AS date) as datetime)

  UNION ALL

  SELECT
    qryInventorySimulation.CDay,
    qryInventorySimulation.InvAcct,
    qryInventorySimulation.BuyerCode,
    qryInventorySimulation.PartNumber,
    qryInventorySimulation.ROP,
    qryInventorySimulation.ROP_ROQ,
    qryInventorySimulation.DailyDemand,
    qryInventorySimulation.StartingInvQty,
    qryInventorySimulation.SchedDeliveryQty,
    CAST(CTE.ProjInvQty + qryInventorySimulation.SchedDeliveryQty - qryInventorySimulation.DailyDemand AS decimal(18,4)) AS ProjInvQty
  FROM
    qryInventorySimulation INNER JOIN CTE ON qryInventorySimulation.InvAcct = CTE.InvAcct AND qryInventorySimulation.PartNumber = CTE.PartNumber AND qryInventorySimulation.CDay = DATEADD(d,1,CTE.CDay)
  WHERE
    qryInventorySimulation.CDay <= DATEADD(d,120,GETDATE())
)

SELECT * FROM CTE
OPTION (MAXRECURSION 0);

【问题讨论】:

    标签: sql sql-server-2008 common-table-expression


    【解决方案1】:

    您不能在视图中应用此选项。您需要将其应用于调用视图的查询。例如

    CREATE VIEW dbo.V
    AS
        WITH CTE AS
        (   SELECT 1 AS A 
            UNION ALL
            SELECT A + 1
            FROM    CTE
            WHERE   A < 50
        )
        SELECT  *
        FROM    CTE;
    GO
    SELECT  *
    FROM    dbo.V
    OPTION (MAXRECURSION 0);
    

    如果您将视图更多地视为存储子查询而不是存储查询(是的,它可以自己调用,但不一定),请记住它的定义已扩展到主查询(除非您是使用NOEXPAND - 无论如何你不能在包含递归CTE的视图上),所以本质上你正在尝试做这样的事情:

    WITH RecursiveCTE AS (...)
    SELECT *
    FROM T
        INNER JOIN 
        (   SELECT  *
            FROM    RecursiveCTE
            OPTION (MAXRECURSION 0)
        ) c
            ON c.SomeField = T.SomeField;
    

    而正确的语法是:

    WITH RecursiveCTE AS (...)
    SELECT *
    FROM T
        INNER JOIN 
        (   SELECT  *
            FROM    RecursiveCTE
        ) c
            ON c.SomeField = T.SomeField;
    OPTION (MAXRECURSION 0)
    

    【讨论】:

    • 感谢您周到的解释和示例,但我仍然无法将其应用于我的情况。我把我的 CTE 保存为一个单独的视图(在你的例子中我们称之为“V”)。然后我创建了另一个视图,如下所示:'SELECT * FROM V OPTION (MAXRECURSION 0);'但是当我保存新视图时仍然存在同样的问题:“关键字选项附近的语法不正确”。我认为这遵循了您的示例。我做错了什么?
    • 我还注意到,如果我将 MAXRECURSION 选项添加到存储过程中 CTE 定义的末尾,则它会被接受。它不会在视图中被接受。尽管它在存储过程中被接受,但它仍然对最大递归数没有任何影响。很奇怪。
    • "然后我创建了另一个视图,如下所示:SELECT * FROM V OPTION (MAXRECURSION 0); 但还是同样的问题" - 这是否令人惊讶?无论您嵌套视图多少次,您都无法对其应用查询提示。它本身不是一个完整的查询,因此不能有提示。
    • "虽然它在存储过程中被接受,但它仍然对最大递归数没有任何影响。奇怪。" - 它确实有效果- see this example
    • @GarethD 看看我是否理解正确。视图是子查询,因为SELECT * FROM theview; 表示SELECT * FROM (SELECT …);。因此,您可以在视图中执行的操作仅限于您可以在子查询中执行的操作,其中不包括提示和ORDER BY 子句(解决方法除外)。我想这同样适用于回答我的另一个问题的表值函数。这很有帮助。
    猜你喜欢
    • 1970-01-01
    • 2016-06-08
    • 2013-12-16
    • 1970-01-01
    • 2013-08-02
    • 2017-11-22
    • 1970-01-01
    • 2018-06-16
    • 2013-10-29
    相关资源
    最近更新 更多