Conversa sobre a cláusula GO

Cláusula GO, funcionamento básico e seus conceitos
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:

Cláusula Go 1

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:

go2

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.

go3

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):

go4

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.

6 pensamentos sobre “Conversa sobre a cláusula GO

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s