【问题标题】:Should we end stored procedures with the GO statement?我们应该用 GO 语句结束存储过程吗?
【发布时间】:2014-06-09 19:07:48
【问题描述】:

我们是否应该用GO语句结束存储过程,如果可以,使用GO有什么好处?

CREATE PROCEDURE uspGetAddress @City nvarchar(30)
AS
SELECT * 
FROM AdventureWorks.Person.Address
WHERE City = @City
GO

【问题讨论】:

  • GO 只是 SSMS 执行前面语句的命令。它本身不是有效的 SQL。它对您的存储过程的影响为零。
  • @Siyual 那么为什么互联网上的许多存储过程示例都使用 GO
  • GO 将语句分成它们自己的批处理以单独运行。 Create Procedure 只能在批处理中唯一的情况下运行。因此,在Create Procedure 之前和之后使用GO 终止语句将确保它可以运行。但如果这是你唯一的声明,那就没有意义了。

标签: sql sql-server tsql stored-procedures


【解决方案1】:

声明goper the documentation

向 SQL Server 实用程序发出一批 Transact-SQL 语句结束的信号。

...

GO 不是 Transact-SQL 语句;它是 sqlcmd 和 osql 识别的命令 实用程序和 SQL Server Management Studio 代码编辑器。

SQL Server 实用程序将GO 解释为它们应该发送当前批处理的信号 到 SQL Server 实例的 Transact-SQL 语句。当前批次语句 由自上次 GO 或自 临时会话或脚本,如果这是第一个 GO

Transact-SQL 语句不能与GO 命令占用同一行。然而,线 可以包含 cmets。

用户必须遵守批量规则。例如,存储过程的任何执行 在批处理中的第一条语句之后必须包含EXECUTE 关键字。范围 本地(用户定义的)变量仅限于一个批次,并且不能在一个批次之后被引用 GO 命令。

存储过程定义per the documentation for create procedure 带有一些限制。它必须是批处理中的第一个(也是唯一一个)语句:

CREATE PROCEDURE 语句不能与中的其他 Transact-SQL 语句结合使用 一个批次。

这意味着存储过程的主体以批处理结束。在源文件中添加GO 是一种很好的做法。特别是因为在创建存储过程之前和之后做一些事情是很常见的。您经常会看到如下所示的源文件:

if (object_id('dbo.foobar') is not null ) drop procedure dbo.foobar
GO
-- dbo.foobar --------------------------------------------
-- 
-- This stored procedure does amazing and wonderful things
----------------------------------------------------------
create procedure dbo.foobar
as

   ...
   {a sequence of amazing and wonderful SQL statements}
   ...
   return 0
GO

grant execute on dbo.foobar to some_schema
GO

GO 的值可以在 Sql Server Management Studio 的选项中调整。如果您想使用 jump 之类的东西而不是 go,您可以(请记住,这样做几乎肯定会让自己感到悲伤。)。

【讨论】:

  • 能否请您帮忙解答这个问题,stackoverflow.com/questions/24127813/…
  • @osman:那里没有太多“帮助”。 Transact-SQL 语法使as 可选,(根据create function 的文档)[msdn.microsoft.com/en-us/library/ms186755(v=sql.110).aspx]。使用它,或者不使用它:它没有区别。我的偏好是省略可选关键字,一般来说,在我看来,它们会使源代码混乱并降低信噪比。所以我说left join而不是left outer joinjoin而不是inner join
【解决方案2】:

不,您应该以RETURN 结束您的程序。

 CREATE PROCEDURE uspGetAddress @City nvarchar(30)
 AS
   SELECT * 
   FROM AdventureWorks.Person.Address
   WHERE City = @City

 RETURN

GO 真的是用来分隔 sql 脚本中的命令。

【讨论】:

  • 存储过程和函数都必须使用 AS 语句吗?
  • 为什么要使用return语句,可以不使用吗?
  • 所有程序在技术上都会返回一些东西,这是一种很好的编码习惯,但您不必这样做。
  • 应该使用明确的return 0 终止存储过程,而不是依赖于默认返回码零 (0)。
  • 当我在SSMS中启动一个新过程时,起始代码模板不包含关键字return。我认为没有理由添加它。
【解决方案3】:

只是想指出,如果在存储过程的末尾没有 GO,那么在假定的过程主体结束之后的任何 T-SQL 仍将包含在 proc 的主体中。

例如

CREATE PROCEDURE Foo
BEGIN
    SELECT * FROM dbo.Bar;
END

DROP TABLE dbo.Bar;

在此示例中,运行 EXEC dbo.Foo 最终会删除表,即使它位于 END 之后。为避免这种情况,您需要在END 之后放置一个GO

【讨论】:

  • 这让我大吃一惊。我现在创建程序后总是会使用 GO。
【解决方案4】:

我更喜欢用beginend 语句包围存储过程的主体:

CREATE PROCEDURE uspGetAddress (
    @City nvarchar(30)
) AS
BEGIN
    SELECT * 
    FROM AdventureWorks.Person.Address
    WHERE City = @City;
END;

GO 不是 T-SQL 命令。运行脚本的工具可以理解它。正如documentation 所述:

GO 不是 Transact-SQL 语句;这是一个被认可的命令 sqlcmd 和 osql 实用程序以及 SQL Server Management Studio 代码 编辑。

SQL Server 实用程序将 GO 解释为它们应该发送的信号 当前批次的 Transact-SQL 语句到 SQL 实例 服务器。当前批次语句由所有语句组成 自上次 GO 或自特别会议开始以来输入,或 如果这是第一个 GO,则编写脚本。

顺便说一句,在您的情况下,用户定义的表函数可能比存储过程更合适。

【讨论】:

  • 如果您在编译存储过程时遇到问题,查找错误通常很有用,一次编译一个块,从create procedure 的语句中选择所有内容时间,逐渐扩大选择范围,直到您发现问题。将存储过程主体包含在 begin/end 块中会阻止这样做。
  • @NicholasCarey。 . .如果您想测试它时添加end 而不是go,则不会。
  • 存储过程的主体包含在begin/end中,如果我选择500行存储过程的前50行并按CTL+E编译它,立即语法由于未关闭的开始,将导致错误。正如我所指出的,这种部分编译技术在识别编译错误的位置时通常很有用:逐渐扩展编译内容的范围,直到识别出问题陈述。
猜你喜欢
  • 1970-01-01
  • 2014-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-02
  • 2020-04-03
  • 1970-01-01
  • 2019-02-27
相关资源
最近更新 更多