Quando é que preciso de usar os blocos Begin / End e a palavra-chave Go no servidor SQL?

Alguém pode dizer-me quando e onde preciso de usar os blocos {[[0]} e end no servidor SQL?
Além disso, o que faz exactamente a palavra-chave Go?

Author: a_horse_with_no_name, 2009-07-25

6 answers

IR é como o fim de um guião.

Você pode ter várias demonstrações de criar tabelas, separadas por GO. É uma forma de isolar uma parte do guião de outra, mas submetê-lo num bloco.


O início e o fim são como { e } em C/++/#, Java, etc.

Eles uniram um bloco lógico de código. Eu costumo usar o princípio e o fim no início e no fim de um procedimento armazenado, mas não é estritamente necessário lá. Onde é necessário é para loops, e se declarações, etc, onde você precisa de mais, em seguida, um passo...
IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
   INSERT INTO Log SELECT @id, 'deleted'
   DELETE my_table WHERE id = @id
END
 92
Author: MatBailie, 2010-06-30 14:33:08
Precisas de começar ... Fim de criar um bloco abrangendo mais de uma declaração. Então, se você quisesse fazer duas coisas em uma 'perna' de uma declaração de se, ou se você quisesse fazer mais do que uma coisa no corpo de um laço WHILE, você precisaria colocar essas declarações no início...FINAL.

A Palavra-chave GO não faz parte do SQL. É usado apenas pelo analisador de consultas para dividir scripts em "lotes" que são executados independentemente.

 29
Author: Gary McGill, 2009-07-24 21:41:25

GO não é uma palavra-chave no servidor SQL; é um separador em lote. GO termina uma série de declarações. Isto é especialmente útil quando você está usando algo como SQLCMD. Imagine que está a introduzir declarações SQL na linha de comandos. Você não quer necessariamente que a coisa para executar cada vez que você terminar uma declaração, então o servidor SQL não faz nada até que você Digite "GO".

Da mesma forma, antes do seu lote começar, você muitas vezes precisa ter alguns objetos visíveis. Por exemplo, digamos que você está criando uma base de dados e depois questioná-la. Não podes escrever.

CREATE DATABASE foo;
USE foo;
CREATE TABLE bar;

Porque o foo não existe para o lote que faz a tabela criar. Tens de fazer isto.

CREATE DATABASE foo;
GO
USE foo;
CREATE TABLE bar;
 21
Author: Dave Markle, 2014-01-13 16:59:32
O início e o fim foram bem respondidos por outros.

Como Gary aponta, GO é um separador de lote, usado pela maioria das ferramentas do cliente fornecidas pela Microsoft, tais como isql, sqlcmd, query analyzer e SQL Server Management studio. (Pelo menos algumas das ferramentas permitem que o separador de lote seja alterado. Nunca vi uso para mudar o separador de lote.)

Para responder à questão de quando usar GO, é preciso saber quando o SQL deve ser separado em lote.

Algumas declarações devem ser a primeira declaração de um lote.

select 1
create procedure #Zero as
    return 0

No servidor sql 2000 o erro é:

Msg 111, Level 15, State 1, Line 3
'CREATE PROCEDURE' must be the first statement in a query batch.
Msg 178, Level 15, State 1, Line 4
A RETURN statement with a return value cannot be used in this context.

No servidor sql 2005 o erro é menos útil:

Msg 178, Level 15, State 1, Procedure #Zero, Line 5
A RETURN statement with a return value cannot be used in this context.

Então, use GO para separar as declarações que têm de ser o início de um lote das declarações que o precedem num script.

Ao executar um script, muitos erros farão com que a execução do lote pare, mas então o cliente irá simplesmente enviar o próximo lote, a execução do script não vai parar. Costumo usar isto nos testes. Vou iniciar o script com a transacção inicial e terminar com a rollback, fazendo todos os testes no meio:

begin transaction
go
... test code here ...
go
rollback transaction
Assim, volto sempre ao estado inicial, mesmo que tenha havido um erro no código de teste, as declarações de operações de início e retrocesso, que fazem parte de lotes separados, continuam a acontecer. Se eles não estivessem em lotes separados, então um erro de sintaxe iria impedir que a transação começasse, uma vez que um lote é processado como uma unidade. E um erro de execução impediria que a rollback acontecesse.

Também, se você estiver fazendo um script de instalação, e tiver vários lotes em um arquivo, um erro em um lote não vai impedir o script de continuar a executar, o que pode deixar uma bagunça. (Sempre backup antes de instalar.)

Relacionado com o que Dave Markel apontou, há casos em que o processamento vai falhar porque o servidor SQL está à procura no dicionário de dados de objetos que são criados anteriormente no lote, mas o processamento pode acontecer antes de qualquer declaração ser executada. Por vezes, trata-se de uma questão, por vezes não. Não consigo dar um bom exemplo. Mas se você alguma vez obter um 'X não existe' erro, quando ele claramente existirá por essa Declaração quebrar em lotes.

E uma nota final. A transacção pode abranger lotes. (Ver acima.) As variáveis não abrangem lotes.

declare @i int
set @i = 0
go
print @i

Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@i".
 10
Author: Shannon Severance, 2010-07-07 16:06:23

GO termina um lote, você só muito raramente precisaria usá-lo em código. Esteja ciente de que se você usá-lo em um proc armazenado, nenhum código após o GO será executado quando você executar o proc.

O início e o fim são necessários para qualquer declaração de tipo processual com linhas multipes de código a processar. Você vai precisar deles para enquanto loops e cursores (que você vai evitar se em tudo possível, é claro) e se declarações (bem techincally você não precisa deles para um IF statment que só tem uma linha de código, mas é mais fácil manter o código se você sempre colocá-los depois de um Fi). As declarações de caso também usam um fim, mas não têm um começo.

 2
Author: HLGEM, 2009-07-24 21:44:52
Depois de lutar com este problema hoje, a minha opinião é esta:: COMECAR...End brackets code just like {....(') em línguas C, por exemplo, blocos de código para Fi...else and loops

GO é (deve ser) usado quando as seguintes declarações dependem de um objecto definido por uma declaração anterior. Usar o banco de dados é um bom exemplo acima, mas o seguinte também irá mordê-lo:

alter table foo add bar varchar(8);
-- if you don't put GO here then the following line will error as it doesn't know what bar is.
update foo set bar = 'bacon';
-- need a GO here to tell the interpreter to execute this statement, otherwise the Parser will lump it together with all successive statements.

Parece-me que o problema é este: o analisador SQL Servidor SQL, ao contrário do Oracle one, é incapaz de perceber que você está definindo um novo símbolo na primeira linha e que está ok para referência nas seguintes linhas. Ele não" vê " o símbolo até que ele encontra um token GO que lhe diz para executar o SQL anterior desde o último GO, em que ponto o símbolo é aplicado ao banco de dados e torna-se visível para o analisador.

Porque não trata o ponto-vírgula Apenas como uma ruptura semântica e aplica declarações individualmente, não sei e gostaria que acontecesse. O único bónus que vejo é que podes pôr um imprimir () declaração imediatamente antes da partida e se alguma das declarações falhar a impressão não será executada. Muitos problemas para um ganho menor.
 1
Author: matao, 2014-10-29 18:48:40