Pregunta

Como parte de mi estrategia de integración, tengo algunos scripts SQL que se ejecutan para actualizar la base de datos.Lo primero que hacen todos estos scripts es verificar si es necesario ejecutarlos, por ejemplo:

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 genial!Excepto si necesito agregar un procedimiento almacenado.El comando "create proc" debe ser el único comando en un lote de comandos SQL.Poner un "crear proceso" en mi declaración IF provoca este error:

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

¡Ay!¿Cómo pongo el comando CREATE PROC en mi script y hago que solo se ejecute si es necesario?

¿Fue útil?

Solución

Esto es lo que se me ocurrió:

Envuélvalo en un EXEC(), así:

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

¡Funciona de maravilla!

Otros consejos

SET NOEXEC ON es una buena manera de desactivar 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

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

PDOtra forma se establece parseely {en | APAGADO }.

Pero tenga cuidado con las comillas simples dentro de su procedimiento almacenado: es necesario "escaparlas" agregando una segunda.La primera respuesta hizo esto, pero en caso de que te lo hayas perdido.Una trampa para jugadores jóvenes.

Versionar su base de datos es el camino a seguir, pero...Por qué crear condicionalmente procedimientos almacenados.Para vistas, procedimientos almacenados y funciones, simplemente suéltelos condicionalmente y vuelva a crearlos cada vez.Si crea condicionalmente, no limpiará las bases de datos que tengan un problema o un truco que otro desarrollador introdujo hace 2 años (tú o yo nunca haríamos esto) que estaba seguro de que recordaría eliminar la única vez. Actualización de emergencia.

El problema al soltar y crear es que se pierden las concesiones de seguridad que se habían aplicado previamente al objeto que se está descartando.

Debo admitir que normalmente estaría de acuerdo con @Peter: dejo caer condicionalmente y luego vuelvo a crear incondicionalmente cada vez.Me han sorprendido demasiadas veces en el pasado al intentar adivinar las diferencias de esquema entre bases de datos, con o sin algún tipo de control de versiones.

Dicho esto, tu propia sugerencia @Josh es genial.Ciertamente interesante.:-)

Este es un hilo antiguo, pero Jobo se equivoca:El procedimiento de creación debe ser la primera declaración de un lote.Por lo tanto, no puedes usar Exists para probar la existencia y luego usar cualquiera de los dos Create o Alter.Lástima.

Mi solución es verificar si el proceso existe, si es así, suéltelo y luego cree el proceso (la misma respuesta que @robsoft pero con un ejemplo...)

IF EXISTS(SELECT * FROM sysobjects WHERE Name = 'PROC_NAME' AND xtype='P') 
BEGIN
    DROP PROCEDURE PROC_NAME
END
GO
CREATE PROCEDURE PROC_NAME
    @value  int
AS
BEGIN
    UPDATE  SomeTable
    SET     SomeColumn = 1
    WHERE   Value = @value
END
GO

use el comando 'Existe' en T-SQL para ver si el proceso almacenado existe.Si es así, use 'Alterar', de lo contrario use 'Crear'

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top