Vamos falar um pouco sobre o comando GO?
Duas pequenas observações antes de começar o artigo:
1) Nada nessa vida, nem uma cláusula de programação, é por acaso;
2) GO não é um comando T-SQL, muito menos SQL padronizado…É um comando usado pelo client para separação de batch (lote).
Introdução
O GO não é um comando T-SQL e também não é reconhecido como padrão na linguagem SQL. É um comando usado pelos aplicativos ‘clients’ que se conectam à instâncias do SQL Server, como, por exemplo, o sqlcmd e o Management Studio, que entendem o GO como um separador de instruções, e por isso enviam o código de modo organizado, por sequência, usando GO como um separador. Se você usar o GO em qualquer client que não tenha suporte à cláusula, o seu código dará erro.
Pra ilustrar o que é batch e como o GO age no SQL Server, vamos a um exemplo básico:
O segundo SELECT dará erro por motivos óbvios. Alguns pensam “mas esse erro não tem lógica! Eu já declarei a variável na janelinha do Management Studio e a janelinha representa uma sessão aberta (até aqui correto), então, a variável, já que foi declarada na sessão, deveria ser reconhecida em qualquer parte da sessão (e aqui mora o erro). Engano clássico.
É justamente este pensamento que possibilita a ocorrência de uma quantidade assustadora de erros em programação T-SQL, simplesmente por ignorar que existem escopos e escopos.
Ilustrando da melhor forma possível como funciona a separação de lotes a mesma consulta acima:
Perceba que o GO delimita um lote de código de acordo com sua declaração, considerando qualquer código até que haja outro GO, que é a delimitação deste comando.O Management Studio, nesse caso, diz pra cada lote até onde ele deve executar. Em declarações de variáveis com o uso de GO, o Management Studio limita o escopo (alcance) da variável @data.
Outro detalhe, o comando GO precisa estar sozinho na linha, caso contrário, dará erro. Se quiser pode testar deixando um GO mesmo antecedido com ponto e vírgula (;) e notará que dará erro. Só comprova que ele é um comando com característica procedural, daqueles da moda antiga, que gostam realmente de separar instruções por lote de código (lote = batch):
E pra que eu uso o GO afinal sendo que ele pode me levar à erros?
O comando tem uma propriedade de contador (inteiro). Isso pode ser usado em nosso favor quando usamos um client com suporte à cláusula. Segue um exemplo fantasioso que preenche uma tabela com registros totalmente aleatórios. Agora, vamos trabalhar com o modo de separação que é nativo do GO além do atributo de repetição.
Basicamente, o GO vai executar 1000 vezes as instruções que foram declaradas desde o último GO. Agora, uma pergunta. Se você der um F5, CTRL+E, PLAY, o que seja, pra executar o código, o que acontece?
a) Um erro;
b) O SQL Server cria a tabela #serial e insere mil vezes nessa tabela através do comando INSERT INTO;
c) Vai executar MIL VEZES o comando SELECT * from #serial;
d) Vai dar USE no banco MASTER mil vezes;
Imagine mentalmente o GO dizendo assim: “Quero executar TUDO que tá emcima de mim. Tudo é meu, ATÉ QUE EU ENCONTRE OUTRO GO, aí o lote de código não é meu. Irmão não invade território de irmão!”.
Aliás, de curiosidade, saiba que o comando GO possui implícitamente a forma GO 1, pois ele só executa aquela instrução de código uma vez. Resumindo o que acontece na questão…
– O primeiro GO vai executar uma vez o comando USE máster
– O segundo GO vai executar o comando CREATE TABLE #serial e o INSERT mil vezes e…
Isso mesmo. A opção correta era a A. Ele vai criar a tabela, inserir uma vez e vai voltar de novo no loop, só que na segunda vez, ele vai voltar pro primeiro comando do lote que é um CREATE TABLE, porém como a tabela já existe, vai dar erro.
Msg 2714, Level 16, State 6, Line 3
There is already an object named ‘#serial’ in the database.
** An error was encountered during execution of batch. Continuing.
Batch deu erro e foi abortado. Simples assim. Então, imagine que você não tem essa tabela #serial. Drope-a:
DROP TABLE #serial
Repare a diferença testando o código abaixo (Não liga para os rabiscos paint-fast-like):
O código acima irá funcionar. Vai executar apenas o INSERT (e não o CREATE) mil vezes. Simples assim.
FAQ (Recapitulando)
É certo dizer que GO é um comando?
Reposta: É sim.
Mas você disse que ele não é um comando..
Resposta: De novo, é um comando sim, relaxa. Do client, e não do SQL ANSI ou T-SQL. Tanto que se você tentar executar uma procedure com GO, dará erro, porque o SQL Server é um Server e não sabe o que significa a cláusula GO.
Posso executar código por código então, sem usar o GO, uma porção de cada vez, no mouse, sabe, na mão?
Claro que pode. E isso, inclusive, é execução em “batch” também (teoricamente). A diferença é que você está fazendo sua própria separação de lotes, mas repare que o conceito é o mesmo.
Para maiores dúvidas:
GO: Documentação do próprio MSDN
Batch: Documentação do próprio MSDN
Qualquer dúvida, feedback, sugestão, sinta-se à vontade para comentar.
Show de bola Renatooo! Excelente post!
Obrigado pelo feedback, Rodrigo!
Renatão muito bem comentado sobre o GO!!!! Então lets’GOOOOO!!!!
Valeu pelo feedback, Patrocínio!
Fera!
Acompanhando o blog =)
Mouse, bom te ver por aqui! Valeu pelo retorno!