2009-07-24 21 views

Respuesta

84

GO es como el final de un guión.

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.


comienzan y terminan son como {y} en C// # ++, Java, etc.

Ataron a 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í. En caso de que se necesita es que los bucles y sentencias IF, etc., donde se necesita más que 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 
+0

¿Has intentado crear un SP sin BEGIN y END? IIRC, solo la primera línea está incluida en el SP, el resto solo se ejecuta allí y luego ... – cjk

+1

Esa no es ciertamente mi experiencia desde SQL Server 2000 en adelante. – MatBailie

29

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.

+1

+1 para escribir más rápido :) – MatBailie

+0

+1 Conciso y preciso – Frozenskys

19

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 puede escribir:

CREATE DATABASE foo; 
USE foo; 
CREATE TABLE bar; 

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

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

GO termina un lote, muy pocas veces necesitaría 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.

+0

¿Algún código después del GO realmente se almacenará contra el proceso almacenado? ¿la sentencia CREATE o ALTER no se procesaría como si hubiera código después de que GO no existiera? Y ENTONCES el código después del GO se ejecuta como si fuera su propio script? – MatBailie

+0

¿Qué tienen que ver los cursores? –

+0

Bueno, en realidad, necesita un bucle para hacer uso de un cursor ... – MatBailie

8

BEGIN y END han sido bien respondidos por otros.

Como señala Gary, 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 utilizar GO, es necesario saber cuándo se debe separar el SQL en lotes.

Algunas afirmaciones 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 menor útil:

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

lo tanto, utilizar GO para separar las declaraciones que tienen que estar el comienzo de un lote a partir de las declaraciones que lo preceden en un script.

Al ejecutar 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. Voy a empezar el guión con iniciar la transacción para terminar con rollback, haciendo todas las pruebas en el medio:

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

De esa manera siempre vuelvo a la situación de partida, incluso si ocurrió un error en el código de prueba, el comienzo y las declaraciones de transacciones de 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á realizando 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 lío. (Hacer una copia de seguridad siempre antes de la instalación.)

Relacionado con lo que Dave Markel señaló, hay casos en que el análisis fallará 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 cualquier declaración se ejecuta. 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". 
+1

Esto es lo que necesitaba, gracias: "La transacción puede abarcar lotes. Las variables no abarcan lotes". – Gary

1

Después de luchar con este problema hoy en día mi opinión es la siguiente: BEGIN ... END código entre paréntesis al igual {....} hace en lenguajes C, por ejemplo, bloques de código para if ... else y loops

GO es (debe ser) utilizado cuando las instrucciones sucesivas dependen de un objeto definido por una instrucción anterior. base de datos de uso es un buen ejemplo de arriba, pero el siguiente también le muerde:

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 el problema es el siguiente: el SQL Analizador de SQL Server, a diferencia de la de Oracle uno, no es capaz de darse cuenta de que' re definir un nuevo símbolo en la primera línea y 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 los enunciados individualmente, no sé y ojalá 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.

Cuestiones relacionadas