【问题标题】:Incorrect syntax near the keyword 'with'.关键字“with”附近的语法不正确。
【发布时间】:2011-08-11 20:30:58
【问题描述】:

您好,我想弄清楚为什么在 MSSQL 中将我的兼容性模式从 80 切换到 100 会破坏下面的函数?

    Microsoft SQL Server 2008 R2 (RTM) - 10.50.1617.0 (X64)   Apr 22 2011 19:23:43
Copyright (c) Microsoft Corporation  Express Edition with Advanced Services (64-bit) on
Windows NT 6.1 <X64> (Build 7601: Service Pack 1)

这是我的功能:

GO
ALTER FUNCTION [dbo].[GetRoot] 
(
    @Param1 int 
)
RETURNS varchar(50)
AS
BEGIN
DECLARE @ReturnValue varchar(50)
with results as
    (
        select parentouid,net_ouid from net_ou where net_ouid=@Param1
        union all
        select t2.parentouid,t2.net_ouid from net_ou t2 
        inner join results t1 on t1.parentouid = t2.net_ouid where t2.parentouid <> t1.net_ouid
    )   
    select @ReturnValue = net_ou.displayname 
    from  NET_OU RIGHT OUTER JOIN
    results ON net_ou.net_ouid = results.ParentouID where results.parentouid=results.net_ouid

    RETURN @ReturnValue

END

【问题讨论】:

    标签: sql sql-server sql-server-2008


    【解决方案1】:

    尝试在 with 前面加上一个分号:

    ;with results as
        (
            select parentouid,net_ouid from net_ou where net_ouid=@Param1
            union all
            select t2.parentouid,t2.net_ouid from net_ou t2 
            inner join results t1 on t1.parentouid = t2.net_ouid where t2.parentouid <> t1.net_ouid
        )   
    

    阅读this article 以了解您为什么需要这样做。片段:

    但是,如果 CTE 不是批处理中的第一个语句,则必须 在 WITH 关键字前加分号。作为最佳实践,我 更喜欢在我所有的 CTE 前加上分号——我发现这个 一致的方法比必须记住我是否需要一个 分号与否。

    就我个人而言,我不会为每个 CTE 都这样做,但如果这让你的事情变得更容易,那不会有任何伤害。

    【讨论】:

    • 没问题。查看我的更新以了解为什么会修复它。
    • 显然,30 秒有什么不同! :) 无论如何 +1。
    • +1,如果你没有输入整个查询,所有这些多汁的代表可能都是你的!
    • 哈哈,太真实了!还可能想向 OP 指出它是声明,因此如果您声明多个 CTEs,则只有 WITH 应该有分号(我以前见过有人对此感到困惑)。
    【解决方案2】:

    WITH前加分号:

    ;with results as
        (
            select parentouid,net_ouid from net_ou where net_ouid=@Param1
            union all
            select t2.parentouid,t2.net_ouid from net_ou t2 
            inner join results t1 on t1.parentouid = t2.net_ouid where t2.parentouid <> t1.net_ouid
        )   
        select @ReturnValue = net_ou.displayname 
        from  NET_OU RIGHT OUTER JOIN
        results ON net_ou.net_ouid = results.ParentouID where results.parentouid=results.net_ouid
    
        RETURN @ReturnValue
    
    END
    

    CTE 声明必须是批处理中的第一个命令。

    【讨论】:

      【解决方案3】:

      我建议您采用以分号结束所有语句的做法。这是 ANSI 标准的一部分,将在需要处理另一个数据库时为您提供帮助。无论如何,SQL Server 都在朝着这个方向发展。 SQL Server 2012 现在有更多命令需要分号。

      例如

      ALTER FUNCTION [dbo].[GetRoot] 
          (@Param1 int)
      RETURNS varchar(50)
      AS
      BEGIN
          DECLARE @ReturnValue VARCHAR(50)
          ;
          WITH cteResults 
          AS (SELECT parentouid
                    ,net_ouid 
                FROM net_ou 
               WHERE net_ouid=@Param1
               UNION ALL
              SELECT t2.parentouid,t2.net_ouid 
                FROM net_ou t2 
               INNER JOIN results t1 
                       ON t1.parentouid = t2.net_ouid
               WHERE t2.parentouid <> t1.net_ouid )   
          SELECT @ReturnValue = net_ou.displayname 
            FROM net_ou 
           RIGHT JOIN cteResults 
                   ON net_ou.net_ouid = results.ParentouID
           WHERE results.parentouid=results.net_ouid
          ;   
          RETURN @ReturnValue
          ;   
      END
      ;
      GO
      

      作为一个额外的好处,它使您查询垃圾负载更容易阅读。 ;-)

      【讨论】:

        猜你喜欢
        • 2015-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-08
        • 2013-12-16
        • 2017-11-22
        • 1970-01-01
        • 2018-06-16
        相关资源
        最近更新 更多