Pregunta ¿Cuándo debo usar Begin / End Blocks y la palabra clave Go en SQL Server?


¿Puede alguien decirme cuándo y dónde debo usar begin y end bloques en SQL Server?
Además, ¿qué es exactamente lo que hace el Go palabra clave do?


74
2017-07-24 21:35


origen


Respuestas:


GO es como el final de un script.

Puede tener varias instrucciones CREATE TABLE, separadas por GO. Es una forma de aislar una parte del script de otro, pero enviarlo todo en un bloque.


BEGIN y END son como {y} en C / ++ / #, Java, etc.

Ellos ataron un bloque lógico de código. Tiendo a usar BEGIN y END al principio y al final de un procedimiento almacenado, pero no es estrictamente necesario allí. Donde es necesario es para bucles, y declaraciones IF, etc., donde necesita más de un paso ...

IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
   INSERT INTO Log SELECT @id, 'deleted'
   DELETE my_table WHERE id = @id
END

89
2017-07-24 21:42



Necesita BEGIN ... END para crear un bloque que abarque más de una declaración. Entonces, si quisiera hacer 2 cosas en un 'tramo' de una instrucción IF, o si quisiera hacer más de una cosa en el cuerpo de un ciclo WHILE, necesitaría poner entre corchetes esas declaraciones con BEGIN ... FIN.

La palabra clave GO no es parte de SQL. Solo lo utiliza el Analizador de consultas para dividir las secuencias de comandos en "lotes" que se ejecutan de forma independiente.


29
2017-07-24 21:41



GO no es una palabra clave en SQL Server; es un separador de lotes GO termina un lote de declaraciones. Esto es especialmente útil cuando está usando algo como SQLCMD. Imagine que está ingresando en las declaraciones de SQL en la línea de comando. No necesariamente quiere que la cosa se ejecute cada vez que finaliza una declaración, por lo que SQL Server no hace nada hasta que ingrese "IR".

Del mismo modo, antes de que comience su lote, a menudo necesita tener algunos objetos visibles. Por ejemplo, supongamos que está creando una base de datos y luego consultándola. No puedes escribir

CREATE DATABASE foo;
USE foo;
CREATE TABLE bar;

porque foo no existe para el lote que crea CREATE TABLE. Deberías hacer esto:

CREATE DATABASE foo;
GO
USE foo;
CREATE TABLE bar;

20
2017-07-24 21:43



BEGIN y END han sido bien respondidos por otros.

Como Gary señala, GO es un separador de lotes, utilizado por la mayoría de las herramientas de cliente suministradas por Microsoft, como isql, sqlcmd, analizador de consultas y el estudio de SQL Server Management. (Al menos algunas de las herramientas permiten cambiar el separador de lotes. Nunca he visto un uso para cambiar el separador de lotes).

Para responder a la pregunta de cuándo usar GO, es necesario saber cuándo el SQL debe separarse en lotes.

Algunas declaraciones deben ser la primera declaración de un lote.

select 1
create procedure #Zero as
    return 0

En SQL Server 2000 el error es:

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.

En SQL Server 2005, el error es 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.

Entonces, usa GO para separar las declaraciones que tienen que ser el comienzo de un lote de las declaraciones que lo preceden en un script.

Cuando se ejecuta un script, muchos errores harán que se detenga la ejecución del lote, pero luego el cliente simplemente enviará el siguiente lote, la ejecución del script no se detendrá. A menudo uso esto en las pruebas. Comenzaré el script con begin transaction y finalizaré con rollback, haciendo todas las pruebas en el medio:

begin transaction
go
... test code here ...
go
rollback transaction

De esa manera, siempre regreso al estado inicial, incluso si ocurre un error en el código de prueba, las declaraciones de transacción de inicio y restitución que son parte de lotes separados aún ocurren. Si no estuvieran en lotes separados, entonces un error de sintaxis evitaría que la transacción comience, ya que un lote se analiza como una unidad. Y un error de tiempo de ejecución evitaría que la reversión ocurriera.

Además, si está haciendo una secuencia de comandos de instalación y tiene varios lotes en un archivo, un error en un lote no evitará que la secuencia de comandos continúe ejecutándose, lo que puede dejar un desastre. (Haga una copia de seguridad siempre antes de la instalación).

En relación con lo que Dave Markel señaló, hay casos en que el análisis fracasará porque SQL Server está buscando en el diccionario de datos los objetos que se crearon anteriormente en el lote, pero el análisis puede ocurrir antes de que se ejecute cualquier declaración. A veces esto es un problema, a veces no. No puedo dar un buen ejemplo. Pero si alguna vez aparece el error "X no existe", cuando exista claramente esa ruptura, se dividirá en lotes.

Y una nota final. La transacción puede abarcar lotes. (Ver arriba.) Las variables no abarcan los lotes.

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

Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@i".

8
2017-07-24 22:18



GO termina un lote, solo muy raramente necesitarás usarlo en el código. Tenga en cuenta que si lo usa en un proceso almacenado, no se ejecutará ningún código después del GO cuando ejecute el proceso.

BEGIN y END son necesarios para cualquier enunciado de tipo de procedimiento con líneas de código de múltiples líneas para procesar. Los necesitarás durante MUCHO bucles y cursores (que evitarás si es posible por supuesto) y declaraciones IF (bien técnicamente no los necesitas para una declaración IF que solo tenga una línea de código, pero es más fácil mantenga el código si siempre los pone después de un IF). Las sentencias CASE también usan un END pero no tienen un BEGIN.


2
2017-07-24 21:44



Después de luchar con este problema hoy mi opinión es esta: BEGIN ... END el código de corchetes al igual que {....} lo hace en C idiomas, p. bloques de código para if ... else y loops

GO es (debe ser) utilizado cuando las declaraciones sucesivas se basan en un objeto definido por una declaración anterior. La base de datos USE es un buen ejemplo más arriba, pero la siguiente también te morderá:

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.

Me parece que el problema es este: el analizador SQL Server SQL, a diferencia del Oracle, no puede darse cuenta de que está definiendo un nuevo símbolo en la primera línea y de que está bien hacer referencia en las siguientes líneas. No "ve" el símbolo hasta que encuentra un token GO que le indica que ejecute el SQL anterior desde el último GO, en cuyo punto el símbolo se aplica a la base de datos y se vuelve visible para el analizador.

Por qué no solo trata el punto y coma como una ruptura semántica y aplica declaraciones individualmente, no sé y desearía que lo hiciera. La única bonificación que puedo ver es que puedes poner una instrucción print () justo antes del GO y si alguna de las instrucciones falla, la impresión no se ejecutará. Sin embargo, muchos problemas para una ganancia menor.


1
2018-04-19 13:39