【问题标题】:Stored Procedure With CTE Fails to Create使用 CTE 的存储过程无法创建
【发布时间】:2016-05-19 14:46:03
【问题描述】:

我测试了这个查询,该查询是在另一个线程的帮助下构建的,它工作得很好,将它移到一个存储过程中,我需要向它提供一个参数(EID 的值)。因此,我对完美测试的查询所做的唯一更改是在顶部和底部添加 @param1 参数,并在顶部添加创建过程行。

我无法保存它,因为它在第 4 行和 'n' 声明中窒息 - SQL80001:'n' 不是一个可识别的选项。

要达到这一点,还有很长的路要走。有人可以帮我推过终点吗?

CREATE PROCEDURE [dbo].[UpdateSubIdx]
@param1 varchar(30) 

WITH n AS 
(
SELECT  DID AS DID,
        sub_idx AS current_id,
        ROW_NUMBER() OVER (PARTITION BY EID ORDER BY alt_sub_idx) AS new_id
FROM    GETT_Documents 
)
--SELECT * FROM N
UPDATE  GETT_Documents
        SET sub_idx = n.new_id
FROM    GETT_Documents  G
JOIN    n ON N.DID = G.DID
WHERE   EID = 'AC-1.1.i';

---Repeat for the alt sub idx column renumberation
WITH n AS 
(
SELECT  DID AS DID,
        alt_sub_idx AS current_id,  
ROW_NUMBER() OVER (PARTITION BY EID ORDER BY sub_idx)*10 AS new_id
  FROM    GETT_Documents 
 )

UPDATE  GETT_Documents
        SET alt_sub_idx = n.new_id
FROM    GETT_Documents  G
JOIN    n ON N.DID = G.DID
WHERE   EID = @param1;

问候, 肯...

【问题讨论】:

    标签: sql sql-server sql-server-2008 stored-procedures


    【解决方案1】:

    您需要在 WITH 关键字之前加上一个分号 (;) 以终止前一个语句。

    公用表表达式必须以 ; 开头 - 可以在此处阅读更多信息:Why should a CTE start with a semi-colon?

    您还需要使用AS BEGIN ... END 来标记过程的主体。以下是应该起作用的更改:

    CREATE PROCEDURE [dbo].[UpdateSubIdx] @param1 varchar(30) 
    As Begin
    
        ;WITH n AS 
        (
        SELECT  DID AS DID,
                sub_idx AS current_id,
                ROW_NUMBER() OVER (PARTITION BY EID ORDER BY alt_sub_idx) AS new_id
        FROM    GETT_Documents 
        )
        --SELECT * FROM N
        UPDATE  GETT_Documents
                SET sub_idx = n.new_id
        FROM    GETT_Documents  G
        JOIN    n ON N.DID = G.DID
        WHERE   EID = 'AC-1.1.i';
    
        ---Repeat for the alt sub idx column renumberation
        ;WITH n AS 
        (
        SELECT  DID AS DID,
                alt_sub_idx AS current_id,  
        ROW_NUMBER() OVER (PARTITION BY EID ORDER BY sub_idx)*10 AS new_id
          FROM    GETT_Documents 
         )
    
        UPDATE  GETT_Documents
                SET alt_sub_idx = n.new_id
        FROM    GETT_Documents  G
        JOIN    n ON N.DID = G.DID
        WHERE   EID = @param1;
    End
    

    【讨论】:

    • 我同意您的代码有效并且您获得了赞成票,但我不同意您应该以分号开头的 cte。分号是语句终止符,而不是语句开始符。并且程序不需要 BEGIN/END。最初的 cte 当然不需要前导分号,而第二个现在有两个。
    • 在这种情况下我不同意BEGIN/END。尝试创建以 CTE 开头但不包含 BEGIN ... END 的过程将失败,原因有两个之一:在 WITH 之前没有 ; 导致无法识别 CTE 名称,或者(在这种情况下,;存在)Incorrect syntax near ';'. 错误。在这种特殊情况下,AS BEGIN ... END 是必需的。
    • 这不是真的。您可以创建一个没有 BEGIN/END 的过程,并且第一行是一个 cte 并且没有分号,完全没有问题。请记住,cte 要求前一行以分号结束。这里看看这个。 sqlfiddle.com/#!6/35eb7/1
    • 采用了 begin 和 end 语句并否定了分号。这是我的第一次存储过程,因此非常感谢您的帮助!
    • @SeanLange Ah - 缺少的关键字是 AS。我在我的测试中包含了AS BEGIN 而不仅仅是BEGIN,这给了我这些结果。你是对的!
    猜你喜欢
    • 2015-07-24
    • 2016-11-19
    • 1970-01-01
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-10
    相关资源
    最近更新 更多