我知道在SQL Server中GO 被认为是批处理分隔符.
我的问题是:有一个批处理分隔符有什么意义?它给你带来了什么好处,为什么要使用它?
示例:我经常看到它在SQL代码中使用如下,我不明白为什么它被认为是最佳实践.据我所知,代码在没有所有GO语句的情况下都是一样的:
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
Run Code Online (Sandbox Code Playgroud)
(来源:technet文档):
Mar*_*ith 37
在这个例子中,没有任何用处.
然而,许多陈述必须是批次中的唯一陈述.
如CREATE PROCEDURE.
通常在进行模式更改(例如,向现有表添加新列)之后,使用新模式的语句必须在不同的批处理中单独编译.
通常,提交分隔的单独批次的替代方法GO是使用子批处理执行SQLEXEC
Pau*_*ams 29
正如TechNet所说,GO它表示SQL批处理结束SQL实用程序.例如,当SQL Server Management Studio遇到批处理分隔符时,它知道到目前为止所有文本都是独立的SQL查询.
我们在软件中使用了类似的技术.我们将所有的proc,模式脚本,数据转换等保存在SQL脚本文件中(签入源代码管理).当我们的安装程序读取其中一个脚本文件时,GO会告诉我们的解析器"您可以运行已经读过的SQL".
关于批处理分隔符的一个很好的功能GO是,您可以在同一脚本中包含两个SQL查询,这些脚本通常会导致错误.例如,尝试在同一个脚本文件中删除并重新创建相同的存储过程:
if exists (select * from sys.procedures where name = 'sp_test')
drop procedure sp_test
create procedure sp_test as
begin
select 1
end
Run Code Online (Sandbox Code Playgroud)
如果您运行上面的代码,您将收到一个错误:
消息156,级别15,状态1,过程sp_test,行5关键字'begin'附近的语法不正确.
SSMS会向您显示错误:
语法不正确.'CREATE PROCEDURE'必须是批次中唯一的声明.
使用批处理分隔符可以帮助您解决此错误:
if exists (select * from sys.procedures where name = 'sp_test')
drop procedure sp_test
GO
create procedure sp_test as
begin
select 1
end
Run Code Online (Sandbox Code Playgroud)
如果您希望源代码管理中的单个SQL脚本维护存储过程或函数,则这非常方便.我们经常使用这种模式.
您可以做的另一个有趣的事情是使用它多次运行查询:
INSERT INTO MyTable (...) ...
GO 10 -- run all the above 10 times!
Run Code Online (Sandbox Code Playgroud)
正如这个SO问题的答案所示,您也可以将其配置为您想要的任何内容.如果您想弄乱您的同事,请将批处理分隔符设置为"WHERE"而不是"GO".有趣!:)
you*_*gme 21
有一个批处理分离器有什么意义?
阅读了许多答案并发表评论后,这就是我的想法。
真正的问题是“拥有一批有什么意义?”
批处理有两个含义,它们具有一定的意义,还有一个额外的用法go可能很有用:
1.批处理中的所有语句都编译成一个执行计划
作为 SQL 开发人员,我不知道这对您有何影响。但它就在那里。这意味着您不能在同一批次中包含某些语句。例如,您不能在ALTER一个表中添加一列,然后select在同一批次中添加该列- 因为在编译执行计划时,该列不存在可供选择。
我认为对于 SQL Server 是否应该能够在不需要开发人员go在其脚本中包含语句的情况下自行检测到这一点,存在一个公开的争论。此外,文档说 ODBC 连接可能永远不会发出go命令。如果包含刚刚给出的ALTER/SELECT示例,我不清楚通过 ODBC 运行的脚本的行为方式。
2. 局部声明的变量只存在于声明它们的批处理范围内
这两点结合起来有点糟糕。我有一个创建和更改数据库结构(表、过程等)的脚本,我想在脚本的开头声明变量,这些变量将用于管理脚本的整体行为。一旦我需要结束一个批处理(例如,由于一个ALTER语句 - 参见我上面的第 1 点),那些“配置”变量就超出了范围,无法在脚本的进一步下方使用。我的解决方法是创建一个表,将配置变量保存到表中,然后通过我的脚本一直从该表中读取,然后在最后删除该表(以防其他人面临这种情况)。
这第二个含义实际上可以被利用 - 如果您的脚本正在做大量工作并且您只想清除所有局部变量,您可以简单地包含一个GO语句,然后声明新变量(即。并重新使用相同的名字,如果这是你想要的)。
3. GO 有一个可选参数(名为“count”),它告诉服务器多次重复批处理操作
这种用法似乎是添加到GO语句中的不错的附加功能。我相信 的初始或主要功能GO更多地与单个执行计划的编译有关,如第 1 点所述 - 否则关键字也可能类似于REPEAT 10- 但重复什么?批次。在不GO表示批处理的情况下,重复命令只能重复之前的单个语句。因此GO是重复批次的好方法。
参考
所有这些都来自于试图理解GO 上的MS 文档。许多其他答案 - 在这里以及其他问题 - 选择文档的一部分,但我认为文档本身并没有真正解释为什么首先批处理有好处 - 因此我对已经得到很好评论的贡献题。
附录
写完上面的内容后,我确实在文档中找到了微软提到的使用批处理的规则GO。链接页面解释了一个执行计划由多个语句组成。它还表示可以将单个语句重新编译为新的执行计划(即由 SQL Server 在处理批处理时自动)。因此,例如,按照对CREATE TABLE您的陈述可能会INSERT进入该表。这INSERT表已事先声明在创建后声明将被重新编译。
这再次强化了这样一种想法,即 SQL Server 可能可以检测ALTER到表后跟 aSELECT并且它需要重新编译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 关键字。
就像Martain所说的那样,CREATE PROCEDURE等语句必须是批量中唯一的.
例如,每当我创建存储过程并向某个用户添加权限时,我都会使用批处理分隔符.如果我省略了'go',那么我最终会得到一个存储过程,每次运行时都会授予权限.通过这种方式,我可以同时编写它们,并确保在编写它们时我不会编写存储过程.例如
create procedure [procedurename]
(parameters)
as begin
select prefname, lastname from people
end
go
grant execute on [procedurename] to [username]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17296 次 |
| 最近记录: |