2008-09-10 11 views
20

Como parte de mi estrategia de integración, tengo algunos scripts SQL que se ejecutan para actualizar la base de datos. La primera cosa que todos estos scripts hacer es comprobar para ver si necesitan para funcionar, por ejemplo .:¿Cómo creo condicionalmente un procedimiento almacenado en SQL Server?

if @version <> @expects 
    begin 
     declare @error varchar(100); 
     set @error = 'Invalid version. Your version is ' + convert(varchar, @version) + '. This script expects version ' + convert(varchar, @expects) + '.'; 
     raiserror(@error, 10, 1); 
    end 
else 
    begin 
     ...sql statements here... 
    end 

funciona muy bien! Excepto si necesito agregar un procedimiento almacenado. El comando "create proc" debe ser el único comando en un lote de comandos sql. Poner una "Crear proc" en mi instrucción IF provoca este error:

 
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch. 

Ay! ¿Cómo coloco el comando CREATE PROC en mi script, y solo lo ejecuto si es necesario?

Respuesta

20

Esto es lo que ocurrió:

lo envuelve en un exec(), así:

if @version <> @expects 
    begin 
     ...snip... 
    end 
else 
    begin 
     exec('CREATE PROC MyProc AS SELECT ''Victory!'''); 
    end 

funciona como un encanto!

+2

Volver a crear los procesos cada vez (condicionalmente soltar) es una solución mucho mejor.Si usa Exec, no gana nada y hay desventajas; su proc tiene que escapar de las cadenas y cualquier número de línea en los errores se referirá al número de línea relativo al comando exec. – Peter

+0

+1 por ser capaz de manejar condiciones distintas a la existencia (en mi caso @@ La versión maneja si se crean o no ciertos procesos) – cmsjr

+1

+1 - Usé esto para configurar mi generador CRUD para crear un procedimiento de código auxiliar si no lo hizo existir, y _then_ alterarlo. Esto me permite modificar mis procesos almacenados, crear el CRUD pero _preservar los permisos asignados contra los procesos existentes_. –

5

Pero tenga cuidado con las comillas simples dentro de su Procedimiento almacenado: deben "escaparse" agregando una segunda. La primera respuesta ha hecho esto, pero solo en caso de que te lo hayas perdido. Una trampa para jugadores jóvenes.

+0

esta respuesta debería ser un comentario. ¿Por qué no lo mueves allí? – Luiso

3

Versionar su base de datos es el camino a seguir, pero ... ¿Por qué crear condicionalmente procedimientos almacenados? Para Vistas, procedimientos almacenados, funciones, simplemente colóquelos condicionalmente y recíclelos cada vez. Si crea condicionalmente, entonces no limpiará las bases de datos que tienen un problema o un truco que pusieron hace 2 años otro desarrollador (usted o yo nunca haríamos esto) que estaba seguro de que recordaría eliminar la única vez actualización de emergencia.

1

Debo admitir que, normalmente, estaría de acuerdo con @Peter - Dejo caer condicionalmente y luego recreé incondicionalmente todo el tiempo. Me han atrapado demasiadas veces en el pasado cuando intentaba adivinar las diferencias de esquema entre bases de datos, con o sin cualquier forma de control de versión.

Habiendo dicho eso, tu propia sugerencia @Josh es genial. Ciertamente interesante. :-)

0

Problema al abandonar y crear es que pierde las concesiones de seguridad que se habían aplicado previamente al objeto que se descarta.

+0

Es solo un problema si no vuelve a agregar esas concesiones después de que se vuelva a crear el procedimiento ;-). –

0
IF NOT EXISTS(SELECT * FROM sys.procedures WHERE name = 'pr_MyStoredProc') 
BEGIN 

    CREATE PROCEDURE pr_MyStoredProc AS ..... 
    SET NOCOUNT ON 
END 

ALTER PROC pr_MyStoredProc 
AS 
SELECT * FROM tb_MyTable 
0

utilice el comando 'Existe' en T-SQL para ver si existe el proceso almacenado. Si lo hace, use 'Alter', sino use 'Crear'

0

Este es un hilo viejo, pero Jobo es incorrecto: Crear Procedimiento debe ser la primera instrucción en un lote. Por lo tanto, no puede usar Exists para probar la existencia y luego usar Create o Alter. Lástima.

+0

Verdadero :) (Por cierto, eso debería ser probablemente un comentario, en lugar de una respuesta. Pero entiendo que no puedes "comentar" todavía;) – Leigh

4

SET NOEXEC ON es una buena manera de apagar alguna parte del código

IF NOT EXISTS (SELECT * FROM sys.assemblies WHERE name = 'SQL_CLR_Functions') 
    SET NOEXEC ON 
GO 
CREATE FUNCTION dbo.CLR_CharList_Split(@list nvarchar(MAX), @delim nchar(1) = N',') 
RETURNS TABLE (str nvarchar(4000)) AS EXTERNAL NAME SQL_CLR_Functions.[Granite.SQL.CLR.Functions].CLR_CharList_Split 
GO 
SET NOEXEC OFF 

encontrar aquí: https://codereview.stackexchange.com/questions/10490/conditional-create-must-be-the-only-statement-in-the-batch

P. S. Otra forma es SET PARSEONLY {ON | APAGADO }.

Cuestiones relacionadas