¿Cómo creo condicionalmente un procedimiento almacenado en SQL Server?
-
09-06-2019 - |
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?
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