Estoy generando un script para migrar automáticamente los cambios de varias bases de datos de desarrollo a la etapa de preparación / producción. Básicamente, se necesitan varios scripts de cambio y los fusiona en un solo script, envolviendo cada script en una IF whatever BEGIN ... END
declaración.
Sin embargo, algunos de los scripts requieren una GO
declaración para que, por ejemplo, el analizador de SQL conozca una nueva columna después de que se cree.
ALTER TABLE dbo.EMPLOYEE
ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO -- Necessary, or next line will generate "Unknown column: EMP_IS_ADMIN"
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
Sin embargo, una vez que envuelvo eso en un IF
bloque:
IF whatever
BEGIN
ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
END
Falla porque estoy enviando un BEGIN
mensaje sin coincidencia END
. Sin embargo, si elimino el GO
, vuelve a quejarse de una columna desconocida.
¿Hay alguna forma de crear y actualizar la misma columna dentro de un solo IF
bloque?
sql
sql-server
tsql
sql-server-2008
BlueRaja - Danny Pflughoeft
fuente
fuente
GO
debe estar en una línea por sí solo, por lo que puede buscar solo ese caso, y no todas las instancias de la palabraGO
. 2) Siempre puede registrar qué declaraciones se completaron correctamente. O puede envolver todo en un try / catch y usar sus propios números de línea usando alguna variable, como @lineNo, de la que realiza un seguimiento e informa sobre el error. Dado que los está generando automáticamente, realizar cambios como este debería ser muy sencillo. Parece que simplemente no quieres explorar esta ruta cuando creo que hay soluciones para todas tus preocupaciones.Respuestas:
Tuve el mismo problema y finalmente logré resolverlo usando SET NOEXEC .
fuente
SQLCMD
script de modo SS (es decir, un script de implementación maestro) que llama (a través de un:r
comando) a otros scripts SS (es decir, scripts de subdespliegue) con algunas de esas llamadas dentro deif
declaraciones. Las Respuestas de Oded, Mellamokb y Andy Joiner de incluir todas esas Declaraciones enexec
Llamadas /begin
-end
no son para empezar. Además, el métodobegin
-end
no funcionará si hay unacreate
instrucción (por ejemplo, requiere ungo
previo explícito ). Pero, hombre, "¡Santos dobles negativos, Batman!" ;)if
), prefijaría el bloque con un-- If whatever
comentario, sangraría el bloque y fijaría el bloque con un--end If whatever
comentario.GO
no es SQL, es simplemente un separador de lotes utilizado en algunas herramientas de MS SQL.Si no lo usa, debe asegurarse de que las declaraciones se ejecuten por separado, ya sea en diferentes lotes o mediante el uso de SQL dinámico para la población (gracias @gbn):
fuente
IF
bloque.;
aquí? - Acaba de editar su respuesta: o);
tampoco funciona: el analizador todavía me da "Nombre de columna no válido 'EMP_IS_ADMIN'".Puede intentar
sp_executesql
dividir el contenido entre cadaGO
declaración en una cadena separada para que se ejecute, como se muestra en el siguiente ejemplo. Además, hay una variable @statementNo para rastrear qué declaración se está ejecutando para una fácil depuración donde ocurrió una excepción. Los números de línea estarán relacionados con el comienzo del número de declaración relevante que causó el error.También puede ejecutar fácilmente declaraciones de varias líneas, como se demuestra en el ejemplo anterior, simplemente envolviéndolas entre comillas simples (
'
). No olvide escapar las comillas simples contenidas dentro de la cadena con una comilla simple doble (''
) al generar los scripts.fuente
SELECT * <newline> FROM whatever
. Si ejecuto cada línea con su propia declaración EXEC, eso se romperá. ¿O estás sugiriendo que rompa con cadaGO
declaración?Finalmente logré que funcionara reemplazando cada instancia de
GO
en su propia línea conEsto es muy preferible a envolver cada grupo de declaraciones en una cadena, pero aún está lejos de ser ideal. Si alguien encuentra una solución mejor, publíquela y la aceptaré.
fuente
IF
bloque). Parece que simplemente no hay una buena manera de hacer esto en SQL.set noexec
respuesta de Mina Jacob es la ÚNICA respuesta práctica hasta ahora para usar en unSQLCMD
script en modo SS (es decir, un script de implementación maestro) que llama (a través de un:r
comando) a otros scripts SS (es decir, scripts de subdespliegue) con algunas de esas llamadas dentro deif
declaraciones. Las Respuestas de Oded, Mellamokb y Andy Joiner de incluir todas esas Declaraciones enexec
Llamadas /begin
-end
no son para empezar. Además, el métodobegin
-end
no funcionará si hay unacreate
instrucción (por ejemplo, requiere ungo
previo explícito ).Puede incluir las declaraciones en BEGIN y END en lugar del GO entre
(Probado en la base de datos Northwind)
Editar: (Probablemente probado en SQL2012)
fuente
set noexec
respuesta de Mina Jacob es la ÚNICA respuesta práctica hasta ahora para usar en unSQLCMD
script de modo SS (es decir, un script de implementación maestro) que llama (a través de un:r
comando) a otros scripts SS (es decir, scripts de subdespliegue) con algunas de esas llamadas dentro deif
declaraciones. Las Respuestas de Oded, Mellamokb y Andy Joiner de incluir todas esas Declaraciones enexec
Llamadas /begin
-end
no son para empezar. Además, el métodobegin
-end
no funcionará si hay unacreate
instrucción (por ejemplo, requiere ungo
previo explícito ).Puede probar esta solución:
fuente
He usado
RAISERROR
en el pasado para estofuente
Puede incorporar declaraciones
GOTO
yLABEL
para omitir el código, dejando lasGO
palabras clave intactas.fuente