2009-04-06 13 views
7

Tengo una situación donde quiero comprobar una determinada columna (como el número de versión) y luego aplicar un montón de ddl cambiaejecutan las instrucciones de DDL condicionales en el servidor SQL

problema es que no soy capaz de hacerlo con en un bloque IF BEGIN END, ya que las sentencias DDL requieren un separador GO entre ellas, y TSQL no lo permitirá.

Me pregunto si hay alguna manera alrededor de lograr esto

Respuesta

0

GO es reconocido por las herramientas del cliente, no por el servidor. Puede tener CREATE en sus procedimientos almacenados o consultas ad-hoc sin GO.

1

¿Múltiples declaraciones "IF"? Puede probar el éxito de las siguientes sentencias DDL

SQL dinámico? EXEC ('ALTER TABLE foo WITH CHECK ADD CONSTRAINT ...')?

Como se mencionó, GO es un separador de lote de cliente único para dividir un solo bloque de texto SQL en lotes que se envían al servidor SQL.

+0

SQL dinámico se convertiría desordenado muy pronto, ya que tengo SQL dinámico dentro de los propios procedimientos –

+0

OK, múltiples instrucciones IF ... luego – gbn

6

No necesita utilizar un bloque completo. Un condicional ejecutará la siguiente instrucción en su totalidad si no utiliza un BEGIN/END, incluyendo una sola instrucción DDL. Esto es equivalente al comportamiento de si en Pascal, C, etc. Por supuesto, eso significa que tendrá que volver a verificar su condición una y otra vez. También significa que el uso de variables para controlar el comportamiento del guión es casi imposible.

[Editar: CREATE procedimiento no funciona en el ejemplo de abajo, así que lo cambiaron a otra cosa y se trasladó CREATE PROCEDURE para una discusión más extendida abajo]

If ((SELECT Version FROM table WHERE...) <= 15) 
CREATE TABLE dbo.MNP (
.... 
) 
GO 

If ((SELECT Version FROM table WHERE...) <= 15) 
ALTER TABLE dbo.T1 
ALTER COLUMN Field1 AS CHAR(15) 
GO 

... 

O algo por el estilo, dependiendo de cual es tu condición

Desafortunadamente, CREAR/ALTERAR PROCEDIMIENTO y CREAR/ALTERAR VER tienen requisitos especiales que hacen que sea mucho más difícil trabajar con él. Se requiere que sean lo único en una declaración, por lo que no se pueden combinar con IF.

Para muchos escenarios, cuando se quiere "actualizar" sus objetos, se puede trabajar como una gota condicional seguido de un crear:

IF(EXISTS(SELECT * FROM sys.objects WHERE type='p' AND object_id = OBJECT_ID('dbo.abc'))) 
DROP PROCEDURE dbo.abc 
GO 

CREATE PROCEDURE dbo.abc 
AS 
    ... 
GO 

Si realmente necesita lógica condicional para decidir qué hacer , entonces la única forma que conozco es usar EXECUTE para ejecutar las instrucciones DDL como una cadena.

If ((SELECT Version FROM table WHERE...) <= 15) 
EXECUTE 'CREATE PROC dbo.abc 
AS 
    .... 
') 

Pero esto es muy doloroso. Tiene que escapar de las comillas en el cuerpo del procedimiento y es realmente difícil de leer.

Dependiendo de los cambios que necesite aplicar, puede ver que todo esto puede ponerse muy feo rápidamente. Lo anterior ni siquiera incluye la comprobación de errores, que es un dolor real por sí solo. Esta es la razón por la cual hordas de fabricantes de herramientas se ganan la vida al descubrir formas de automatizar la creación de scripts de implementación.

Lo sentimos; no hay una manera fácil y "correcta" que funcione para todo. Esto es algo que TSQL soporta muy mal. Aún así, lo anterior debería ser un buen comienzo.

+0

Si ((SELECT Versión FROM tabla WHERE ...) <= 15) CREAR PROCEDIMIENTO dbo.abc AS esta sintaxis no funcionará ... dice Sintaxis incorrecta cerca de la palabra clave 'PROCEDIMIENTO' –

+1

¡Está en lo correcto! Lo siento. ¿Ver? Te dije que estaba desordenado (me enseña a responder una pregunta a las 2 a.m.). T-SQL requiere que CREATE PROC sea la ÚNICA instrucción en un "lote" (entre GO). Arreglé el ejemplo anterior y te proporcioné más detalles sobre el problema. Buena suerte. –

Cuestiones relacionadas