我是SQL Server 2012的新手,我正在尝试创建一个应该存储的存储过程:
但是我需要使用 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子句包含在它自己的事务中,这也不起作用,总是得到两个错误之一。
任何指针都将非常感谢,谢谢!
答案 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时, 之前的陈述必须后跟分号。
如前所述,最佳做法是:
我更喜欢第一个,但我见过有能力的开发人员更喜欢第二个。