【问题标题】:What is a "batch", and why is GO used?什么是“批处理”,为什么要使用 GO?
【发布时间】:2011-02-09 17:51:46
【问题描述】:

我已经阅读并阅读过 MSDN 等。好的,所以它标志着批处理的结束。

什么定义了批次?当我粘贴一堆脚本以同时运行时,我不明白为什么我需要去。

我从来没有理解过 GO。谁能更好地解释这一点以及我何时需要使用它(在多少或什么类型的交易之后)?

例如,为什么每次更新后我都需要 GO:

 UPDATE [Country]
   SET [CountryCode] = 'IL'
 WHERE code = 'IL'

 GO

 UPDATE [Country]
   SET [CountryCode] = 'PT'
 WHERE code = 'PT'

【问题讨论】:

标签: tsql


【解决方案1】:

GO 不是正确的 TSQL 命令。

相反,它是对特定客户端程序的命令,该程序连接到 SQL 服务器(Sybase 或 Microsoft 的 - 不确定 Oracle 做了什么),向客户端程序发出信号:输入到它,直到“go”需要发送到服务器执行。

您为什么/何时需要它?

  • MS SQL server 中的 GO 有一个“count”参数 - 因此您可以将其用作“重复 N 次”快捷方式。

  • 非常大的更新可能会填满 SQL 服务器的日志。为避免这种情况,可能需要通过go 将它们分成更小的批次。

    在您的示例中,如果一组国家/地区代码的更新量如此之大以至于日志空间不足,则解决方案是将每个国家/地区代码分成一个单独的事务 - 这可以通过将它们分开来完成客户go

  • 某些 SQL 语句必须用 GO 与以下语句分开才能正常工作。

    例如,您不能在单个事务中删除表并重新创建同名表,至少在 Sybase 中是这样(创建过程/触发器也是如此):

> drop table tempdb.guest.x1          
> create table tempdb.guest.x1 (a int)
> go
  Msg 2714, Level 16, State 1
  Server 'SYBDEV', Line 2
  There is already an object named 'x1' in the database.   
  
> drop table tempdb.guest.x1          
> go
> create table tempdb.guest.x1 (a int)
> go
>

【讨论】:

  • GO 语句不创建事务。如果您在一个 BEGIN TRANSACTION 语句中包含多个 GO 语句,最后您将执行 ROLLBACK,它将回滚所有 GO。而如果在一个 GO 中间你会得到一些错误,最后你会做 COMMIT,所有没有错误的 GO 都会被提交。有点棘手。
  • GO 不会“为您创建交易”。如果您没有在显式事务中运行,则每个语句都会创建自己的事务。它是完全正交的。如果您想将较大的更新拆分为较小的步骤,您仍然可以像常见的WHILE @@ROWCOUNT > 0 模式一样在单个批次中进行。
  • 如果您没有在显式事务中运行,那么UPDATE T1 SET X =2;UPDATE T1 SET X =2; 将作为两个单独的事务运行无论如何。添加GO 完全没有区别。同样,如果您正在在显式事务中运行,它会跨越批次,GO 没有区别。
  • 正如稍后阅读此内容的任何人的澄清......GO 与事务完全无关,并且使关于事务和日志文件大小的第二点的答案不正确。 GO 将不起作用。第一个和第三个答案是正确的。此外,有时您需要将语句分成单独的批次,例如,您不能将列添加到表中,然后稍后在同一批次中使用该列。 (续)
  • 另外,因为有些错误会中止一个批处理(有些错误只是中止一个语句),它也起到了错误检测和恢复的作用。并且某些语句(CREATE VIEW 等)需要在它们自己的批处理中。
【解决方案2】:

GO 不是语句,而是批处理分隔符。

GO分隔的块由客户端发送到服务器进行处理,客户端等待它们的结果。

例如,如果你写

DELETE FROM a
DELETE FROM b
DELETE FROM c

,这将作为单个 3-line 查询发送到服务器。

如果你写

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

,这将作为3 单行查询发送到服务器。

GO 本身不会访问服务器(不是双关语)。纯客户端保留字,只有SSMSosql能识别。

如果您将使用自定义查询工具通过连接发送它,服务器甚至不会识别它并发出错误。

【讨论】:

  • 为什么一定要批处理??
  • 那么 GO 表示发送它,然后在客户端收到“OK,该批次完成并成功”之前不要运行下一批,基本上就是 GO 所做的,以便下一批可以成功运行,客户端在服务器端完成之前肯定知道批处理。
  • @coffeeaddict:基本上,是的。另外,有些语句需要在它们的批次中排在第一位(比如CREATE SCHEMA);其他要求是其批次中的 only 语句(如 SET SHOWPLAN_XML ON
【解决方案3】:

许多命令需要在自己的批处理中,例如CREATE PROCEDURE

或者,如果您将一列添加到表中,那么它应该在自己的批次中。 如果您尝试在同一批次中选择新列,则会失败,因为在解析/编译时该列不存在。

SQL 工具使用 GO 从一个脚本中解决此问题:它不是 SQL 关键字,引擎无法识别。

这些是批次日常使用的 2 个具体示例。

编辑:在您的示例中,您不需要 GO...

编辑 2,示例。你不能在一个批次中删除、创建和权限...尤其是,存储过程的结尾在哪里?

IF OBJECT_ID ('dbo.uspDoStuff') IS NOT NULL
    DROP PROCEDURE dbo.uspDoStuff
GO
CREATE PROCEDURE dbo.uspDoStuff
AS
SELECT Something From ATable
GO
GRANT EXECUTE ON dbo.uspDoStuff TO RoleSomeOne
GO

【讨论】:

    【解决方案4】:

    有时需要一遍又一遍地执行相同的命令或一组命令。这可能是插入或更新测试数据,也可能是在您的服务器上增加负载以进行性能测试。不管需要什么,最简单的方法是设置一个 while 循环并执行您的代码,但在 SQL 2005 中,有一种更简单的方法来做到这一点。

    假设您要创建一个测试表并加载 1000 条记录。您可以发出以下命令,它会运行相同的命令 1000 次:

    CREATE TABLE dbo.TEST (ID INT IDENTITY (1,1), ROWID uniqueidentifier)
    GO
    INSERT INTO dbo.TEST (ROWID) VALUES (NEWID()) 
    GO 1000
    

    来源: http://www.mssqltips.com/tip.asp?tip=1216

    除此之外,它标志着 SQL 块的“结束”(例如在存储过程中)...意味着您再次处于“干净”状态...例如:在代码之前的语句中使用的参数被重置(不再定义)

    【讨论】:

    • 好的,那你为什么需要 GO。这样您就知道该表是在运行插入语句之前创建的吗?我还是不明白。
    • 请参阅我的想法是,如果我在您的示例中没有 GO,则首先创建表,它现在就在那里,因此插入应该可以工作。如果我创建了表,我不明白 GO 的用途......它可用于下一个插入,不是吗?!?!?!
    • @coffeeaddict:没有。 “批处理”被一次性解析和编译。在编译时,dbo.TEST 不存在。您没有实例化一个对象,并且 SQL 不是逐行程序代码
    【解决方案5】:

    正如大家已经说过的,“GO”不是 T-SQL 的一部分。 “GO”是在 SSMS 中的批处理分隔符,它是用于向数据库提交查询的客户端应用程序。这意味着声明的变量和表变量不会从“GO”之前的代码持续到它之后的代码。

    实际上,GO 只是 SSMS 使用的 default 词。如果需要,可以在选项中进行更改。为了好玩,将其他人系统上的选项更改为使用“SELECT”作为批处理分隔符而不是“GO”。原谅我残忍的笑声。

    【讨论】:

    • 这里有一个很严肃的问题:你应该把 GO 当作一个关键字,即使它不是。你也不应该改变它。重用特殊标识符引起的错误可能很难调试。
    • @The Dixie Flatline:你确定声明的变量不会持久化吗?在 MSSQL 2016 中,我在运行时收到“已声明变量”错误: declare $test int;设置 $test = 5;选择 $test 去;声明 $test int; -- 将$替换为,SE cmets中不能使用多个
    【解决方案6】:

    用于分割逻辑块。您的代码被解释为 sql 命令行,这表示下一个代码块。

    但它可以用作具有特定数字的递归语句。

    试试:

    exec sp_who2  
    go 2
    

    有些语句必须用 GO 分隔:

    use DB
    create view thisViewCreationWillFail
    

    【讨论】:

      猜你喜欢
      • 2014-01-09
      • 2017-05-01
      • 2017-06-01
      • 2023-03-13
      • 2011-10-31
      • 1970-01-01
      • 2019-05-26
      • 2011-05-10
      • 2014-01-31
      相关资源
      最近更新 更多