我什么时候需要在SQL Server中使用Begin/End Blocks和Go关键字?

Tar*_*rik 99 t-sql sql-server language-features

有人能告诉我在SQL Server中何时何地需要使用beginend阻止?
此外,该Go关键字到底是做什么的?

Mat*_*lie 106

GO就像脚本的结尾.

您可以有多个CREATE TABLE语句,由GO分隔.这是一种将脚本的一部分与另一部分隔离的方法,但是在一个块中提交它.


BEGIN和END就像C/++ /#,Java等中的{和}一样.

它们绑定了一个逻辑代码块.我倾向于在存储过程的开始和结束时使用BEGIN和END,但在那里并不是绝对必要的.有必要的地方是循环和IF语句等,你需要多一步......

IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
   INSERT INTO Log SELECT @id, 'deleted'
   DELETE my_table WHERE id = @id
END
Run Code Online (Sandbox Code Playgroud)

  • 是的。在外面声明的任何东西在里面都是可见的,但是在里面声明的任何东西都将在 END 处超出范围。 (3认同)
  • 这肯定不是我从SQL Server 2000开始的经验. (2认同)
  • BEGIN 和 END 是否也定义了新的范围? (2认同)

Gar*_*ill 35

你需要BEGIN ... END来创建一个跨越多个语句的块.所以,如果你想在IF语句的一个'leg'中做两件事,或者你想在WHILE循环的主体中做多件事,你需要用BEGIN括起那些语句......结束.

GO关键字不是SQL的一部分.它仅供查询分析器用于将脚本划分为独立执行的"批处理".


Dav*_*kle 25

GO不是SQL Server中的关键字; 这是一个批处理分隔符.GO结束了一批陈述.当您使用SQLCMD之类的东西时,这尤其有用.想象一下,您正在命令行中输入SQL语句.每次结束语句时都不一定要执行该操作,因此在您输入"GO"之前,SQL Server不会执行任何操作.

同样,在批处理开始之前,您经常需要显示一些对象.例如,假设您正在创建一个数据库,然后查询它.你不能写:

CREATE DATABASE foo;
USE foo;
CREATE TABLE bar;
Run Code Online (Sandbox Code Playgroud)

因为执行CREATE TABLE的批处理不存在foo.你需要这样做:

CREATE DATABASE foo;
GO
USE foo;
CREATE TABLE bar;
Run Code Online (Sandbox Code Playgroud)


Sha*_*nce 10

其他人已经很好地回答了BEGIN和END.

正如Gary指出的那样,GO是一个批处理分隔符,由大多数Microsoft提供的客户端工具使用,例如isql,sqlcmd,查询分析器和SQL Server Management工作室.(至少有一些工具允许更改批处理分隔符.我从未见过用于更改批处理分隔符的用途.)

要回答何时使用GO的问题,需要知道何时必须将SQL分成批次.

有些陈述必须是批次的第一个陈述.

select 1
create procedure #Zero as
    return 0
Run Code Online (Sandbox Code Playgroud)

在SQL Server 2000上,错误是:

Msg 111, Level 15, State 1, Line 3
'CREATE PROCEDURE' must be the first statement in a query batch.
Msg 178, Level 15, State 1, Line 4
A RETURN statement with a return value cannot be used in this context.
Run Code Online (Sandbox Code Playgroud)

在SQL Server 2005上,错误不太有用:

Msg 178, Level 15, State 1, Procedure #Zero, Line 5
A RETURN statement with a return value cannot be used in this context.
Run Code Online (Sandbox Code Playgroud)

因此,用于GO将必须是批处理开头的语句与脚本中的语句前面的语句分开.

当运行脚本时,许多错误将导致批处理的执行停止,但随后客户端将简单地发送下一批,脚本的执行不会停止.我经常在测试中使用它.我将使用begin transaction启动脚本并以rollback结束,在中间执行所有测试:

begin transaction
go
... test code here ...
go
rollback transaction
Run Code Online (Sandbox Code Playgroud)

这样我总是返回到起始状态,即使测试代码中发生错误,开始和回滚事务语句仍然是单独批次的一部分.如果它们不是分开的批处理,则语法错误会使开始事务不发生,因为批处理被解析为一个单元.并且运行时错误会阻止回滚发生.

此外,如果您正在执行安装脚本,并且在一个文件中有多个批处理,则一个批处理中的错误将不会使脚本继续运行,这可能会造成混乱.(在安装前始终备份.)

与Dave Markel指出的相关,有些情况下解析会失败,因为SQL Server在数据字典中查找批处理中先前创建的对象,但解析可能在任何语句运行之前发生.有时这是一个问题,有时不是.我无法想出一个好榜样.但是如果你得到一个'X不存在'的错误,当它明确存在时,该声明会分批进入.

最后一点.交易可以跨越批次.(见上文.)变量不跨越批次.

declare @i int
set @i = 0
go
print @i

Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@i".
Run Code Online (Sandbox Code Playgroud)


HLG*_*GEM 5

GO 结束一个批处理,你很少需要在代码中使用它。请注意,如果在存储过程中使用它,则执行过程时不会执行 GO 之后的代码。

对于任何需要处理多行代码的过程类型语句,都需要 BEGIN 和 END。您将需要它们用于 WHILE 循环和游标(当然,如果可能的话,您将避免使用它们)和 IF 语句(从技术上来说,您不需要它们用于只有一行代码的 IF 语句,但更容易如果您总是将代码放在 IF 之后,请维护代码)。CASE 语句也使用 END 但没有 BEGIN。