首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >SQL Server:批处理语句(即使用"GO")有什么好处?

SQL Server:批处理语句(即使用"GO")有什么好处?
EN

Stack Overflow用户
提问于 2013-12-21 04:19:07
回答 4查看 23.6K关注 0票数 90

我在SQL Server GO is considered a batch separator中知道这一点。

我的问题是:,有批次分隔符的意义是什么?,它给你带来了什么好处,你为什么要使用它?

示例:我经常在SQL代码中看到它的使用,如下所示,我不明白为什么它会被认为是最佳实践。据我所知,如果没有所有的GO语句,代码将是相同的:

代码语言:javascript
复制
USE AdventureWorks2012;
GO
BEGIN TRANSACTION;
GO
IF @@TRANCOUNT = 0
BEGIN
    SELECT FirstName, MiddleName 
    FROM Person.Person WHERE LastName = 'Adams';
    ROLLBACK TRANSACTION;
    PRINT N'Rolling back the transaction two times would cause an error.';
END;
ROLLBACK TRANSACTION;
PRINT N'Rolled back the transaction.';
GO

(来源:technet documentation):

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-12-21 04:22:02

在这个例子中,它没有任何用处。

但是,批处理中必须只有许多语句。

例如CREATE PROCEDURE

此外,通常在进行模式更改(例如,向现有表中添加新列)之后,必须在不同的批处理中单独编译使用新模式的语句。

通常,提交由GO分隔的单独批处理的另一种方法是使用EXEC在子批处理中执行SQL

票数 46
EN

Stack Overflow用户

发布于 2013-12-21 05:08:45

作为TechNet saysGO向SQL实用程序表示SQL批处理的结束。例如,当SQL Server Management Studio遇到批处理分隔符时,它知道到目前为止的所有文本都是一个独立的SQL查询。

我们在我们的软件中使用了类似的技术。我们将所有的过程、模式脚本、数据转换等都保存在SQL脚本文件中(签入到源代码控制中)。当我们的安装程序读取其中一个脚本文件时,GO告诉我们的解析器“你可以运行你已经读过的SQL”。

GO这样的批处理分隔符的一个很好的特性是,您可以在同一脚本中包含两个通常会导致错误的SQL查询。例如,尝试删除并在同一脚本文件中重新创建同一存储过程:

代码语言:javascript
复制
if exists (select * from sys.procedures where name = 'sp_test')
    drop procedure sp_test

create procedure sp_test as
begin
    select 1
end

如果你运行上面的代码,你会得到一个错误:

消息156,级别15,状态1,过程sp_test,第5行关键字'begin‘附近的语法不正确。

SSMS将向您显示错误:

语法不正确。“'CREATE”必须是批处理中的唯一语句。

使用批次分隔符可以帮助您解决此错误:

代码语言:javascript
复制
if exists (select * from sys.procedures where name = 'sp_test')
    drop procedure sp_test
GO
create procedure sp_test as
begin
    select 1
end

例如,如果您希望源代码控制中的单个SQL脚本维护存储过程或函数,这将非常方便。我们经常使用这个模式。

您可以做的另一件有趣的事情是使用它来多次运行查询:

代码语言:javascript
复制
INSERT INTO MyTable (...) ...
GO 10 -- run all the above 10 times!

正如the answers to this SO question演示的那样,您还可以将其配置为您想要的任何内容。如果你想惹恼你的同事,把批次分隔符设置成类似于"WHERE“而不是"GO”。有趣!:)

票数 35
EN

Stack Overflow用户

发布于 2019-05-30 08:39:46

有批次分隔符的意义是什么?

在阅读了许多答案并发表了评论后,以下是我的想法。

真正的问题是“拥有批处理的意义是什么?”

批处理有两个含义,go的另一个用法可能会很有用:

1.将批处理中的所有语句编译为一个执行计划

作为一名SQL开发人员,我不知道这对您有什么影响。但事实就是如此。这意味着您不能在同一批处理中包含一些语句。例如,您不能先ALTER表以添加列,然后在同一批处理中select该列-因为在编译执行计划时,该列不存在以供选择。

我认为,对于SQL Server是否应该能够在不要求开发人员在其脚本中包含go语句的情况下自行检测到这一点,存在一个开放的争论。此外,文档还说ODBC connection可能永远不会发出go命令。我不清楚如果包含刚才给出的ALTER / SELECT示例,通过ODBC运行的脚本会有什么行为。

2.本地声明的变量仅存在于它们被声明为的批处理范围内

这两点结合在一起有点糟糕。我有一个创建和更改DB结构(表、过程等)的脚本,我想在脚本的开头声明变量,这些变量将用于管理整个脚本的行为。只要我需要包装一个批处理(例如,由于一条ALTER语句-请参见上面的观点1 ),这些“配置”变量就会超出作用域,并且不能在脚本中进一步使用。我的解决方法是创建一个表,将配置变量持久化到表中,然后通过我的脚本一直从该表中读取,然后在最后删除该表(以防其他人遇到这种情况)。

第二个含义实际上可以用于优势-如果你的脚本正在做大量的工作,而你只是想清除所有的局部变量,你可以简单地包括一个GO语句,然后声明新的变量(即.并重新使用相同的名称,如果这是您想要的)。

3. GO有一个可选参数(名为"count"),它告诉服务器将批处理操作重复多次

这种用法似乎是添加到GO语句中的很好的附加功能。我认为GO的初始或主要功能更多地与编译单个执行计划有关,如第一点所述-否则关键字可能类似于REPEAT 10 -但重复什么?批次。如果不使用GO表示批处理,则重复命令只能重复前面的单个语句。因此,GO是重复批处理的好方法。

参考

所有这些都来自于对MS documentation on GO的理解。许多其他的答案-这里和其他问题-都是针对文档的片段,但我认为文档本身无法真正解释为什么批处理有好处-因此我对一个已经得到很好评论的问题做出了贡献。

附录

写完上面的内容后,我确实在GO文档中找到了微软提到的Rules for Using Batches。该链接页面说明执行计划由多个语句组成。它还说,可以将单个语句重新编译为新的执行计划(即由SQL Server自动处理批处理)。因此,例如,在CREATE TABLE语句之后,您可能有一个到该表的INSERT。在前面的语句中创建表之后,将重新编译该INSERT语句。

这再次强化了这样一种想法,即SQL Server可能会检测到表的ALTER后面跟着SELECT的情况,并且它需要重新编译SELECT (请参见上面的第1点),如果使用ODBC,可能就会发生这种情况(请参见上面的第1点)。

这些新信息都不会改变上面给出的3点。我刚才给出的链接包含额外的阅读内容,并以“规则”结尾,它们是:

  • CREATE DEFAULT、CREATE FUNCTION、CREATE PROCEDURE、CREATE RULE、CREATE SCHEMA、CREATE TRIGGER和CREATE VIEW语句不能与批处理中的其他语句组合。CREATE语句必须启动批处理。该批处理中后面的所有其他语句将被解释为第一个CREATE语句的定义的一部分。
  • 不能更改表,然后在同一批处理中引用新列。
  • 如果EXECUTE语句是批处理中的第一个语句,则不需要EXECUTE关键字。如果EXECUTE语句不是批处理中的第一个语句,则需要EXECUTE关键字。
票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20711326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档