Неверный синтаксис рядом с ключевым словом 'with'.

Здравствуйте, я пытаюсь понять, почему переключение режима совместимости с 80 на 100 в MSSQL нарушило мою функцию ниже?

    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 [email protected]
        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

Ответы

Ответ 1

Попробуйте бросить полуколону перед с:

;with results as
    (
        select parentouid,net_ouid from net_ou where [email protected]
        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
    )   

Дайте эту статью, чтобы понять, зачем вам это нужно. Snipit:

Однако, если CTE не является первым оператором в партии, вы должны перед ключевым словом WITH укажите точку с запятой. Как наилучшая практика, я предпочитают префикс всех моих CTE точкой с запятой - я нахожу это более последовательный подход, чем необходимость помнить, нужна ли мне точка с запятой или нет.

Лично я не делаю этого для каждого CTE, но если это облегчит вам задачу, это ничего не повредит.

Ответ 2

Добавьте точку с запятой до WITH:

;with results as
    (
        select parentouid,net_ouid from net_ou where [email protected]
        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 [email protected]
         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

В качестве дополнительного бонуса вы получаете запросы, которые легче читать.; -)