¿Qué es un "lote" y por qué se utiliza GO?

134

He leído y leído sobre MSDN, etc. Ok, entonces señala el final de un lote.

¿Qué define un lote? No veo por qué necesito ir cuando estoy pegando un montón de scripts para ejecutarlos todos al mismo tiempo.

Nunca he entendido GO. ¿Alguien puede explicar esto mejor y cuándo necesito usarlo (después de cuántas o qué tipo de transacciones)?

Por ejemplo, ¿por qué necesitaría IR después de cada actualización aquí:

 UPDATE [Country]
   SET [CountryCode] = 'IL'
 WHERE code = 'IL'

 GO

 UPDATE [Country]
   SET [CountryCode] = 'PT'
 WHERE code = 'PT'
PositivoGuy
fuente
FWIW, parece que gotambién se restablece / borra declare @foolas declaraciones de variables: estaba obteniendo que necesita declarar errores @foo , hasta que comenté el go.
JL Peyret

Respuestas:

107

GOno es correctamente un comando TSQL.

En cambio, es un comando para el programa cliente específico que se conecta a un servidor SQL (Sybase o Microsoft, no estoy seguro de lo que hace Oracle), indicando al programa cliente que el conjunto de comandos que se ingresaron en él hasta el "ir" necesita para ser enviado al servidor para ser ejecutado.

¿Por qué / cuándo lo necesitas?

  • GO en el servidor MS SQL tiene un parámetro "recuento", por lo que puede usarlo como un acceso directo "repetir N veces".

  • Las actualizaciones extremadamente grandes pueden llenar el registro del servidor SQL. Para evitar eso, es posible que tengan que separarse en lotes más pequeños a través de go.

    En su ejemplo, si la actualización de un conjunto de códigos de país tiene un volumen tal que se quedará sin espacio de registro, la solución es separar cada código de país en una transacción separada, lo que puede hacerse separándolos en el cliente con go.

  • Algunas declaraciones SQL DEBEN estar separadas por GO de las siguientes para que funcionen.

    Por ejemplo, no puede soltar una tabla y volver a crear la tabla con el mismo nombre en una sola transacción, al menos en Sybase (lo mismo para crear procedimientos / disparadores):

> drop table tempdb.guest.x1          
> create table tempdb.guest.x1 (a int)
> go
  Msg 2714, Level 16, State 1
  Server 'SYBDEV', Line 2
  There is already an object named 'x1' in the database.   
  
> drop table tempdb.guest.x1          
> go
> create table tempdb.guest.x1 (a int)
> go
>
DVK
fuente
44
La declaración GO no crea una transacción. Si incluye varias declaraciones GO en una declaración BEGIN TRANSACTION y al final realizará un ROLLBACK, revertirá todos los GO. Y si en un GO en el medio obtendrá algún error, y al final hará COMMIT, todos los GO sin error se comprometerán. Es un poco complicado.
TZ
77
GOno "crea una transacción para usted". Si no está ejecutando una transacción explícita, cada declaración creará su propia transacción de todos modos. Es completamente ortogonal. Si desea dividir una actualización más grande en pasos más pequeños, aún puede hacerlo en un solo lote como en el WHILE @@ROWCOUNT > 0patrón común .
Martin Smith
3
Si no está ejecutando una transacción explícita, UPDATE T1 SET X =2;UPDATE T1 SET X =2;se ejecutará como dos transacciones separadas de todos modos . La adición de no GOhace absolutamente ninguna diferencia. Y de manera similar, si está ejecutando una transacción explícita, abarca lotes y nuevamente GO no hace ninguna diferencia.
Martin Smith
44
Solo como aclaración para cualquiera que lea esto más tarde ... no GOtiene absolutamente nada que ver con las transacciones, y hace que las respuestas sean un segundo punto sobre las transacciones y el tamaño de un archivo de registro incorrecto. GOno tendrá efecto alguno. Las respuestas primera y tercera son correctas. Además, hay momentos en los que necesita separar las declaraciones en lotes separados, por ejemplo, no puede agregar una columna a una tabla y luego usar esa columna más adelante en el mismo lote. (continuación)
Robert McKee
44
Además, debido a que algunos errores anularán un lote (algunos errores solo anularán una declaración), también juega un papel en la detección y recuperación de errores. Y ciertas declaraciones ( CREATE VIEW, etc.) deben estar en su propio lote.
Robert McKee
26

GO No es una declaración, es un separador de lotes.

Los bloques separados por GOson enviados por el cliente al servidor para su procesamiento y el cliente espera sus resultados.

Por ejemplo, si escribes

DELETE FROM a
DELETE FROM b
DELETE FROM c

, esto se enviará al servidor como una 3consulta de una sola línea .

Si tú escribes

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

, esto se enviará al servidor como 3 consultas de una línea.

GOen sí no va al servidor (sin juego de palabras). Es una palabra reservada pura del lado del cliente y solo es reconocida porSSMS y osql.

Si va a utilizar una herramienta de consulta personalizada para enviarla a través de la conexión, el servidor ni siquiera la reconocerá y emitirá un error.

Quassnoi
fuente
44
¿Por qué tienes que hacer un lote?
PositiveGuy
3
Entonces, GO significa enviarlo y luego no ejecutar el siguiente lote hasta que el cliente reciba "OK, ese lote se realizó y fue exitoso", básicamente es lo que hace el GO para que el siguiente lote se pueda ejecutar con éxito y el cliente sepa asegúrese de que el lote se realice antes del lado del servidor.
PositiveGuy
3
@coffeeaddict: básicamente sí. Además, algunas declaraciones requieren ser las primeras en sus lotes (como CREATE SCHEMA); otros requieren ser las únicas declaraciones en sus lotes (como SET SHOWPLAN_XML ON)
Quassnoi
19

Muchos comandos deben estar en su propio lote, como CREATE PROCEDURE

O, si agrega una columna a una tabla, debería estar en su propio lote. Si intenta SELECCIONAR la nueva columna en el mismo lote, falla porque en el momento del análisis / compilación la columna no existe.

GO es utilizado por las herramientas SQL para resolver esto desde un script: no es una palabra clave SQL y el motor no lo reconoce.

Estos son 2 ejemplos concretos del uso diario de lotes.

Editar: en su ejemplo, no necesita IR ...

Edición 2, ejemplo. No puede soltar, crear y autorizar en un lote ... no menos importante, ¿dónde está el final del procedimiento almacenado?

IF OBJECT_ID ('dbo.uspDoStuff') IS NOT NULL
    DROP PROCEDURE dbo.uspDoStuff
GO
CREATE PROCEDURE dbo.uspDoStuff
AS
SELECT Something From ATable
GO
GRANT EXECUTE ON dbo.uspDoStuff TO RoleSomeOne
GO
gbn
fuente
4

A veces es necesario ejecutar el mismo comando o conjunto de comandos una y otra vez. Esto puede ser para insertar o actualizar datos de prueba o puede ser poner una carga en su servidor para pruebas de rendimiento. Cualquiera sea la necesidad, la forma más fácil de hacer esto es configurar un ciclo while y ejecutar su código, pero en SQL 2005 hay una manera aún más fácil de hacerlo.

Supongamos que desea crear una tabla de prueba y cargarla con 1000 registros. Puede emitir el siguiente comando y ejecutará el mismo comando 1000 veces:

CREATE TABLE dbo.TEST (ID INT IDENTITY (1,1), ROWID uniqueidentifier)
GO
INSERT INTO dbo.TEST (ROWID) VALUES (NEWID()) 
GO 1000

fuente: http://www.mssqltips.com/tip.asp?tip=1216

Aparte de eso, marca el "final" de un bloque SQL (por ejemplo, en un procedimiento almacenado) ... lo que significa que está en un estado "limpio" de nuevo ... eG: Parámetros utilizados en la declaración antes de restablecer el código ( ya no está definido)

Steav
fuente
Ok, entonces ¿por qué necesitas ir? ¿Para que sepa que la tabla se creó antes de ejecutar la instrucción de inserción? Aún no lo entiendo.
PositiveGuy
Vea La forma en que pienso sobre esto, es que si no tengo GOs en su ejemplo, la Tabla se crea primero, está allí ahora, por lo que la inserción debería funcionar. No entiendo para qué sirve el GO si creé la tabla ... está disponible para el siguiente inserto, ¿no?!?!?!
PositiveGuy
2
@coffeeaddict: no. el "lote" se analiza y compila de una vez. En tiempo de compilación, dbo.TEST no existe. No está creando instancias de un objeto y SQL no es código de procedimiento línea por línea
gbn
3

Como todos ya dijeron, "IR" no es parte de T-SQL. "IR" es un separador de lotes en SSMS , una aplicación cliente utilizada para enviar consultas a la base de datos. Esto significa que las variables declaradas y las variables de tabla no persistirán del código antes del "IR" al código que lo sigue.

De hecho, GO es simplemente la palabra predeterminada utilizada por SSMS. Esto se puede cambiar en las opciones si lo desea. Para divertirse un poco, cambie la opción en el sistema de otra persona para usar "SELECCIONAR" como separador de lotes en lugar de "IR". Perdona mi cruel risa.

La línea plana de Dixie
fuente
1
Realmente hay un punto serio que hacer aquí: debe tratar GO como si fuera una palabra clave aunque no lo sea. Tampoco deberías cambiarlo nunca. Los errores causados ​​por la reutilización de identificadores especiales pueden ser muy difíciles de depurar.
Jørgen Fogh
@ The Dixie Flatline: ¿estás seguro de que las variables declaradas no persisten? En MSSQL 2016 obtengo un error de "variable ya declarada" cuando ejecuto: declare $ test int; establecer $ prueba = 5; seleccione $ test go; declarar $ prueba int; - Reemplace $ con <at>, no puede usar múltiples <at> en comentarios SE.
Wouter
0

Se utiliza para dividir bloques lógicos. Su código se interpreta en la línea de comando sql y esto indica el siguiente bloque de código.

Pero podría usarse como una declaración recursiva con un número específico.

Tratar:

exec sp_who2  
go 2

Alguna declaración tiene que estar delimitada por GO:

use DB
create view thisViewCreationWillFail
Deadsheep39
fuente