SQL Server存储过程与空体

Luk*_*zda 5 sql t-sql sql-server stored-procedures sql-server-2012

CREATE PROCEDURE语法:

CREATE { PROC | PROCEDURE } [schema_name.] procedure_name [ ; number ]   
    [ { @parameter [ type_schema_name. ] data_type }  
        [ VARYING ] [ = default ] [ OUT | OUTPUT | [READONLY]  
    ] [ ,...n ]   
[ WITH <procedure_option> [ ,...n ] ]  
[ FOR REPLICATION ]   
AS { [ BEGIN ] sql_statement [;] [ ...n ] [ END ] }  
[;]  


<sql_statement> ::=   
{ [ BEGIN ] statements [ END ] }  
Run Code Online (Sandbox Code Playgroud)

[](括号) 可选的语法项.不要键入括号.

{}(大括号) 必需的语法项.不要键入大括号.

人类可读的形式:

在此输入图像描述

让我们尝试用空体写存储过程:

CREATE PROC my_proc AS

-- please treat it as separate call, for example with different session
EXEC my_proc
Run Code Online (Sandbox Code Playgroud)

是完美有效的语法.

LiveDemo

所以看起来这sql_statement可能是空的.

现在让我们尝试相同但这次使用BEGIN/END块:

CREATE PROC my_proc AS
BEGIN
END
-- Incorrect syntax near 'END'.
Run Code Online (Sandbox Code Playgroud)

LiveDemo2

为什么第一个例子有效?如果sql_statement不允许,则第二个示例也应该起作用,或者文档不准确.

编辑

好吧,那是因为在第一个例子中它不是一个空体,你的sp将是:EXEC my_proc

案件是为了表明我可以打电话给SP.但你可以添加GO或使用EXEC:

CREATE PROC my_proc AS
GO

EXEC my_proc
Run Code Online (Sandbox Code Playgroud)

要么

EXEC('CREATE PROC my_proc AS')

EXEC my_proc
Run Code Online (Sandbox Code Playgroud)

LiveDemo3

Gen*_*ari 5

语法错误与存储过程的正确语法无关.它是"BEGIN/END"的正确语法.BEGIN/END要求其中的一些SQL有效.BEGIN/END的文档显示了这一点:

https://msdn.microsoft.com/en-us/library/ms190487.aspx

BEGIN  
     {   
    sql_statement | statement_block   
     }   
END  
Run Code Online (Sandbox Code Playgroud)

CREATE PROC文档中的语法确实不完全正确,因为它表示"CREATE PROC"需要sql_statement,而实际上并不需要它.

  • 语法是问题中提供的书面Backus Naur.问题是为什么实践中的行为与此不同.因此争辩说"它执行所以语法必须说"不是答案. (2认同)