Antes de responder quando usá-lo e por quê, é primeiro fundamental entender exatamente o que GO
é e o que não é.
A palavra GO
- chave é usada pelo SQL Server Management Studio e pelo SQLCMD para significar uma coisa e apenas uma: O final de um lote de instruções. Na verdade, você pode alterar o que você usa para finalizar lotes para algo diferente de "GO":
Essa captura de tela acima é uma opção configurável no SSMS.
Mas o que é um lote? Esta referência BOL diz o melhor:
Um lote é um grupo de uma ou mais instruções Transact-SQL enviadas ao mesmo tempo de um aplicativo para o SQL Server para execução.
Simples assim. É apenas uma maneira personalizada de um aplicativo (sim ... um aplicativo) enviar instruções para o SQL Server. Vamos ver um exemplo disso em aparência de aplicativo. Usarei o PowerShell para imitar o que um aplicativo faria para enviar instruções e lotes para o SQL Server:
$ConnectionString = "data source = SomeSQLInstance; initial catalog = AdventureWorks2012; trusted_connection = true; application name = BatchTesting;"
try {
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.Connection = $SqlConnection
# first batch of statements
#
$SqlCmd.CommandText = "
select * from humanresources.department where departmentid = 1;
select * from humanresources.department where departmentid = 2;
select * from humanresources.department where departmentid = 3;
select * from humanresources.department where departmentid = 4;"
# execute the first batch
#
$SqlConnection.Open()
$SqlCmd.ExecuteNonQuery()
$SqlConnection.Close()
# second batch of statements
#
$SqlCmd.CommandText = "
select * from humanresources.department where departmentid = 5;
select * from humanresources.department where departmentid = 6;
select * from humanresources.department where departmentid = 7;
select * from humanresources.department where departmentid = 8;"
# execute the second batch
#
$SqlConnection.Open()
$SqlCmd.ExecuteNonQuery()
$SqlConnection.Close()
}
catch {
$SqlCmd.Dispose()
$SqlConnection.Dispose()
Write-Error $_.Exception
}
Os comentários revelam isso, mas você pode ver acima que estamos enviando programaticamente dois lotes para o SQL Server. Vamos verificar isso, no entanto. Minha escolha aqui é usar Eventos Estendidos:
create event session BatchTesting
on server
add event sqlserver.sql_batch_starting
(
set
collect_batch_text = 1
where
(
sqlserver.client_app_name = N'BatchTesting'
)
),
add event sqlserver.sql_batch_completed
(
set
collect_batch_text = 1
where
(
sqlserver.client_app_name = N'BatchTesting'
)
),
add event sqlserver.sql_statement_starting
(
set
collect_statement = 1
where
(
sqlserver.client_app_name = N'BatchTesting'
)
),
add event sqlserver.sql_statement_completed
(
set
collect_statement = 1
where
(
sqlserver.client_app_name = N'BatchTesting'
)
)
add target package0.event_file
(
set
filename = N'<MyXelLocation>\BatchTesting.xel'
);
go
alter event session BatchTesting
on server
state = start;
go
Tudo o que esta sessão do XEvents está fazendo é capturar as instruções e lotes que são iniciados e concluídos a partir de um aplicativo chamado "BatchTesting"
(se você observar minha cadeia de conexão no meu exemplo de código do PowerShell, é uma maneira rápida de observar um originador específico de eventos usando o "application nome "parâmetro da cadeia de conexão e filtragem disso).
Depois de executar o código do PowerShell para enviar esses lotes e instruções, vejo os seguintes resultados:
Como você pode ver na captura de tela, é claro como as instruções são divididas em dois lotes diferentes, também evidentes pelos meios que usamos para chamá-los. E se examinarmos batch_text
a primeira ocorrência de sql_batch_starting
, poderemos ver todas as instruções incluídas nesse lote:
select * from humanresources.department where departmentid = 1;
select * from humanresources.department where departmentid = 2;
select * from humanresources.department where departmentid = 3;
select * from humanresources.department where departmentid = 4;
Com essa explicação sobre o que é um lote, agora vem a resposta para sua pergunta sobre quando finalizar lotes. As regras para lotes são encontradas nesta referência BOL em relação aos lotes :
As instruções CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER e CREATE VIEW não podem ser combinadas com outras instruções em um lote. A instrução CREATE deve iniciar o lote. Todas as outras instruções a seguir nesse lote serão interpretadas como parte da definição da primeira instrução CREATE.
Uma tabela não pode ser alterada e, em seguida, as novas colunas referenciadas no mesmo lote.
Se uma instrução EXECUTE for a primeira em um lote, a palavra-chave EXECUTE não será necessária. A palavra-chave EXECUTE será necessária se a instrução EXECUTE não for a primeira no lote.
Da mesma forma, certos erros de tempo de execução (erros de compilação não permitem a execução de um lote) que ocorrem durante um lote podem causar comportamentos diferentes: abortar totalmente o lote ou continuar o lote e abortar apenas a declaração incorreta (a descrição acima O link fornece dois exemplos muito bons: um erro de estouro aritmético, por exemplo, interrompe a execução do lote, enquanto um erro de violação de restrição impede a conclusão da instrução atual, mas o lote continua em execução).
Como muitas coisas em nossa profissão, porém, a preferência pessoal será uma grande força motriz por trás de como você, como indivíduo e escritor do código T-SQL, finaliza lotes. Algumas pessoas definem explicitamente apenas lotes quando precisam (veja os requisitos acima) e outras finalizam lotes programaticamente 100% das vezes , mesmo quando estão executando apenas uma única instrução em uma janela de consulta no SSMS. A maioria das pessoas geralmente cai em algum lugar no meio desses dois limites. Pelo que vale, os terminadores de instruções têm os mesmos seguidores, com também muito poucos requisitos impostos. Grande parte de tudo isso é estilo de código , onde não é imposto (no SSMS e no SQLCMD).