在SQL Server 2012中的存储过程中执行多个语句和CTE?

时间:2015-03-04 04:19:51

标签: sql-server tsql stored-procedures sql-server-2012 common-table-expression

我是SQL Server 2012的新手,我正在尝试创建一个应该存储的存储过程:

  1. 根据参数删除表中的先前数据,然后
  2. 在该表上插入新数据。
  3. 但是我需要使用 CTE 来表现性能和其他原因(不要挂断,我必须,只听我的话)。

    如果CTE查询本身存在于存储过程中,则它可以正常工作,但我不能让SP使用两个子句。

    我在尝试创建程序时遇到错误,抱怨我应该在CTE之前使用分号。如果我添加分号,SQL Server也会抱怨它。这让我疯了,请帮助

    我要删除/插入的表格:

    CREATE MYTABLE ( APPUSER NVARCHAR(15), DATA NVARCHAR(100) )
    

    简化存储过程(无分号):

    CREATE PROCEDURE P1 ( @SOMEUSER NVARCHAR(15), @TYPE INTEGER) AS
    BEGIN
        DELETE FROM MYTABLE WHERE ( APPUSER=@SOMEUSER )
    
        WITH CTE AS (
            SELECT DATA
            FROM SOURCETABLE
            WHERE ( TYPE = @TYPE )
        )
        INSERT INTO MYTABLE
        SELECT
            @SOMEUSER,
            DATA
        FROM CTE 
    END
    

    没有分号的错误消息:

      

    [错误代码:319,SQL   状态:S1000]关键字'with'附近的语法不正确。如果这   statement是一个公用表表达式,一个xmlnamespaces子句或一个   更改跟踪上下文子句,必须是前面的语句   以分号结束。

    请注意,尽管这是实际查询的简化版本,但错误完全相同。我确实尝试了上面的代码,没有任何运气:(

    带分号的存储过程(与上面相同的查询,为简洁起见仅显示分号):

    (...)
    BEGIN
        DELETE FROM MYTABLE WHERE ( APPUSER=@SOMEUSER ); /* Semicolon */
    
        WITH CTE AS (    
    (...)
    

    分号出错:

      

    [错误代码:102,SQL状态:42000]')'附近的语法不正确。

    我尝试将DELETE子句包含在它自己的事务中,这也不起作用,总是得到两个错误之一。

    任何指针都将非常感谢,谢谢!

3 个答案:

答案 0 :(得分:5)

你需要放一个';'在'With'关键字之前,您的代码看起来像这样

CREATE PROCEDURE P1 ( @SOMEUSER NVARCHAR(15), @TYPE INTEGER) AS
BEGIN
    DELETE FROM MYTABLE WHERE ( APPUSER=@SOMEUSER )

    ;WITH CTE AS (
        SELECT DATA
        FROM SOURCETABLE
        WHERE ( TYPE = @TYPE )
    )
    INSERT INTO MYTABLE
    SELECT
        @SOMEUSER,
        DATA
    FROM CTE 
END

作为CTE的拇指规则,如果您的CTE上方有任何可执行语句,请始终以分号开头。

答案 1 :(得分:3)

你有一些奇怪的事情,因为以下内容对我有用:

CREATE PROCEDURE P1 ( @SOMEUSER NVARCHAR(15), @TYPE INTEGER) AS
BEGIN
    DELETE FROM [Table_1] WHERE ( [lname]=@SOMEUSER );

    WITH CTE AS (
        SELECT [fname], [lname]
        FROM [Table_1]
        WHERE ( [ID] = @TYPE )
    )
    INSERT INTO [Table_1]
    SELECT top 1
        @SOMEUSER,
        [lname],
        @TYPE
    FROM CTE 
END

检查您的环境

CTE只是语法 - 它没有帮助提高性能

答案 2 :(得分:0)

为了完全明确其他人提出的观点,此摘录形式the MSDN documentation on CTE's in SQL Server是使用CTE的重要注意事项:

  

•在作为批次一部分的语句中使用CTE时,   之前的陈述必须后跟分号。

如前所述,最佳做法是:

  • 养成用分号结束所有SQL语句的习惯;或
  • 学习并记住所有必需的分号,例如此处,并在其中加上所有这些结构。

我更喜欢第一个,但我见过有能力的开发人员更喜欢第二个。