O que é um "lote" e por que o GO é usado?

134

Eu li e li no MSDN, etc. Ok, então sinaliza o final de um lote.

O que define um lote? Não vejo por que preciso ir quando estou colando vários scripts para serem executados ao mesmo tempo.

Eu nunca entendi GO. Alguém pode explicar isso melhor e quando eu preciso usá-lo (depois de quantas ou que tipo de transações)?

Por exemplo, por que eu precisaria do GO após cada atualização aqui:

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

 GO

 UPDATE [Country]
   SET [CountryCode] = 'PT'
 WHERE code = 'PT'
PositiveGuy
fonte
1
possível duplicata de Qual é o uso do GO no SQL Server Management Studio?
tvanfosson
FWIW, parece que um gotambém redefine / limpa declare @foodeclarações de variáveis ​​- eu estava conseguindo que você declarasse erros do @foo , até que comentei o go.
JL Peyret

Respostas:

107

GOnão é corretamente um comando TSQL.

Em vez disso, é um comando para o programa cliente específico que se conecta a um servidor SQL (Sybase ou Microsoft - não tem certeza sobre o que a Oracle faz), sinalizando ao programa cliente que o conjunto de comandos que foram inseridos nele até a necessidade de "ir" para ser enviado ao servidor para ser executado.

Por que / quando você precisa?

  • O GO no MS SQL Server possui um parâmetro "count" - para que você possa usá-lo como um atalho "repetir N vezes".

  • Atualizações extremamente grandes podem preencher o log do servidor SQL. Para evitar isso, eles podem precisar ser separados em lotes menores via go.

    No seu exemplo, se a atualização para um conjunto de códigos de países tiver um volume que não excederá o espaço de log, a solução é separar cada código de país em uma transação separada - o que pode ser feito separando-os no cliente go.

  • Algumas instruções SQL DEVEM ser separadas pelo GO das seguintes para funcionar.

    Por exemplo, você não pode descartar uma tabela e recriar a tabela com o mesmo nome em uma única transação, pelo menos no Sybase (idem para criar procedimentos / gatilhos):

> 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
>
DVK
fonte
4
A instrução GO não cria transação. Se você incluir várias instruções GO em uma instrução BEGIN TRANSACTION e, no final, realizar um ROLLBACK, ele reverterá todos os GO. E se em um GO no meio, você receberá algum erro e, no final, fará o COMMIT, todos os GO sem erros serão confirmados. É meio complicado.
TZ
7
GO"não cria uma transação para você." Se você não estiver executando uma transação explícita, cada instrução criará sua própria transação de qualquer maneira. É completamente ortogonal. Se você deseja dividir uma atualização maior em etapas menores, ainda pode fazê-lo em um único lote, como no WHILE @@ROWCOUNT > 0padrão comum .
Martin Smith
3
Se você não estiver executando em uma transação explícita, UPDATE T1 SET X =2;UPDATE T1 SET X =2;será executado como duas transações separadas de qualquer maneira . A adição de não GOfaz absolutamente nenhuma diferença. Da mesma forma, se você estiver executando uma transação explícita, ela abrange lotes e, novamente, GO não faz diferença.
Martin Smith
4
Assim como o esclarecimento para quem lê isso mais tarde ... não GOtem absolutamente nada a ver com transações, e coloca as respostas em segundo lugar sobre transações e o tamanho de um arquivo de log incorreto. GOnão terá nenhum efeito. A primeira e a terceira respostas estão corretas. Além disso, há momentos em que você precisa separar as instruções em lotes separados, por exemplo, não é possível adicionar uma coluna a uma tabela e usá-la posteriormente no mesmo lote. (continuação)
Robert McKee
4
Além disso, como alguns erros abortam um lote (alguns erros abortam apenas uma instrução), ele também desempenha um papel na detecção e recuperação de erros. E certas instruções ( CREATE VIEWetc) precisam estar em seu próprio lote.
Robert McKee
26

GO não é uma declaração, é um separador de lotes.

Os blocos separados por GOsão enviados pelo cliente ao servidor para processamento e o cliente aguarda seus resultados.

Por exemplo, se você escrever

DELETE FROM a
DELETE FROM b
DELETE FROM c

, isso será enviado ao servidor como uma 3consulta de linha única .

Se você escrever

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

, isso será enviado ao servidor como 3consultas de uma linha.

GOem si não vai para o servidor (sem trocadilhos). É uma palavra reservada pura do lado do cliente e é reconhecida apenas por SSMSe osql.

Se você usar uma ferramenta de consulta personalizada para enviá-la pela conexão, o servidor nem sequer a reconhecerá e emitirá um erro.

Quassnoi
fonte
4
Por que você tem que fazer um lote?
PositiveGuy
3
Portanto, GO significa enviá-lo e, em seguida, não execute o próximo lote até que o cliente receba "OK, esse lote foi concluído e foi bem-sucedido" basicamente é o que o GO faz para que o próximo lote possa ser executado com sucesso e o cliente saiba por verifique se o lote antes de ser concluído no servidor.
PositiveGuy
3
@ coffeeaddict: basicamente sim. Além disso, algumas instruções precisam ser as primeiras em seus lotes (como CREATE SCHEMA); outras exigem sendo as únicas declarações em seus lotes (como SET SHOWPLAN_XML ON)
Quassnoi
19

Muitos comandos precisam estar em seu próprio lote, como CREATE PROCEDURE

Ou, se você adicionar uma coluna a uma tabela, ela deverá estar em seu próprio lote. Se você tentar SELECIONAR a nova coluna no mesmo lote, ela falhará porque, no momento da análise / compilação, a coluna não existe.

O GO é usado pelas ferramentas SQL para resolver isso a partir de um script: não é uma palavra-chave SQL e não é reconhecida pelo mecanismo.

Estes são 2 exemplos concretos de uso diário de lotes.

Edit: No seu exemplo, você não precisa de GO ...

Edite 2, exemplo. Você não pode descartar, criar e permissão em um lote ... não menos importante, onde está o fim do procedimento armazenado?

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
gbn
fonte
4

Às vezes, é necessário executar o mesmo comando ou conjunto de comandos repetidamente. Pode ser para inserir ou atualizar dados de teste ou para colocar uma carga no servidor para teste de desempenho. Qualquer que seja a necessidade, a maneira mais fácil de fazer isso é configurar um loop while e executar seu código, mas no SQL 2005 há uma maneira ainda mais fácil de fazer isso.

Digamos que você queira criar uma tabela de teste e carregá-la com 1000 registros. Você pode emitir o seguinte comando e ele executará o mesmo comando 1000 vezes:

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

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

Fora isso, marca o "fim" de um bloco SQL (por exemplo, em um procedimento armazenado) ... Significando que você está em um estado "limpo" novamente ... eG: Parâmetros usados ​​na instrução antes da redefinição do código ( não está mais definido)

Steav
fonte
Ok, então por que você precisa do GO. Para que você saiba que a tabela foi criada antes da execução da instrução insert? Eu ainda não entendi.
PositiveGuy
Veja A maneira como penso sobre isso é que, se eu não tiver GOs no seu exemplo, a Tabela será criada primeiro, ela estará lá agora, portanto a inserção deve funcionar. Eu não entendo para que serve o GO se eu criei a tabela ... está disponível para a próxima inserção, não é?!?!?!
PositiveGuy
2
@coffeeaddict: não. o "lote" é analisado e compilado de uma só vez. No momento da compilação, o dbo.TEST não existe. Você não está instanciar um objeto e SQL não é linha de código processual linha
GBN
3

Como todos já disseram, "GO" não faz parte do T-SQL. "GO" é um separador de lotes no SSMS , um aplicativo cliente usado para enviar consultas ao banco de dados. Isso significa que variáveis ​​declaradas e variáveis ​​de tabela não persistirão do código antes do "GO" para o código após.

De fato, GO é simplesmente a palavra padrão usada pelo SSMS. Isso pode ser alterado nas opções, se você desejar. Para se divertir, altere a opção no sistema de outra pessoa para usar "SELECT" como separador de lotes em vez de "GO". Perdoe minha risada cruel.

The Dixie Flatline
fonte
1
Há realmente um ponto sério a ser mencionado aqui: você deve tratar o GO como se fosse uma palavra-chave, mesmo que não seja. Você também nunca deve mudar isso. Os erros causados ​​pela reutilização de identificadores especiais podem ser muito difíceis de depurar.
Jørgen Fogh
@ The Dixie Flatline: você tem certeza de que as variáveis ​​declaradas não persistem? No MSSQL 2016, recebo um erro "variável já declarada" ao executar: declare $ test int; defina $ test = 5; selecione $ test go; declarar $ test int; - Substitua $ por <at>, não pode usar vários <at> nos comentários do SE.
Wouter
0

É usado para dividir blocos lógicos. Seu código é interpretado na linha de comando sql e isso indica o próximo bloco de código.

Mas poderia ser usado como declaração recursiva com número específico.

Experimentar:

exec sp_who2  
go 2

Alguma declaração deve ser delimitada pelo GO:

use DB
create view thisViewCreationWillFail
Deadsheep39
fonte