Actualización de enero de 2017 - SQL Server 2016+ / Azure SQL Database
SQL Server 2016 y la versión actual de Azure SQL Database ahora tienen la siguiente sintaxis para funciones, procedimientos, tablas, bases de datos, etc. ( DROP IF EXISTS
):
DROP FUNCTION IF EXISTS dbo.fn_myfunc;
Y SQL Server 2016 Service Pack 1 agrega una funcionalidad aún mejor para los módulos (funciones, procedimientos, disparadores, vistas), lo que significa que no se pierden permisos ni dependencias ( CREATE OR ALTER
):
CREATE OR ALTER FUNCTION dbo.fn_myfunc ...
Ambas mejoras de sintaxis pueden conducir a secuencias de comandos mucho más simples que se utilizan para el control de origen, implementaciones, etc.
Pero, si estás usando ...
versiones anteriores
Debe hacer lo que hace SQL Server cuando escribe esto desde Management Studio:
IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE type = 'FN' AND name = 'fn_myfunc')
BEGIN
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'CREATE FUNCTION ...';
EXEC sp_executesql @sql;
END
O puedes decir:
BEGIN TRY
DROP FUNCTION dbo.fn_myfunc;
END TRY
BEGIN CATCH
PRINT 'Function did not exist.';
END CATCH
GO
CREATE FUNCTION...
O simplemente puedes decir:
DROP FUNCTION dbo.fn_myfunc;
GO
CREATE FUNCTION...
(Aquí recibirá un mensaje de error si la función aún no existe, pero la secuencia de comandos continuará desde el próximo GO, por lo que si la caída funcionó o no, la función aún se volverá a crear).
Tenga en cuenta que si suelta la función y la vuelve a crear, también perderá permisos e información de dependencia potencial.
El error se explica por sí mismo. Hay un par de formas de arreglarlo.
Separe el script en diferentes lotes en Management Studio usando la
GO
pseudo-palabra clave yDROP
/CREATE
el objeto. (Tenga en cuenta que la palabra clave en sí misma se puede cambiar en las opciones de Management Studio, pero esta es la configuración de facto, por lo que sugiero dejarla sola).Cuando ejecuta una secuencia de comandos (o la parte seleccionada de una secuencia de comandos), Management Studio separa cada fragmento de secuencia de comandos entre
GO
sy envía secuencialmente las partes a SQL Server como lotes separados.Use SQL dinámico para enviar un lote separado desde otro lote.
Este es el método preferido, porque su script no depende de la funcionalidad externa para ejecutarse correctamente. Por ejemplo, si su aplicación tiene un programa de actualización de la base de datos, en general cargará un archivo de script y luego lo ejecutará en el servidor de destino. Deberá agregar lógica para separar los lotes como lo hace Management Studio (nota: lleno de peligros), o escribir el script de manera que todo el script pueda ejecutarse con éxito como un solo lote.
Como se menciona en otra respuesta, puede hacer una prueba /
CREATE
usar este método (o alguna otra combinación deDROP
/CREATE
, etc.). Lo que prefiero hacer es crear un objeto auxiliar si el objeto no existe, y luego usarloALTER <object>
para hacer la creación o alteración. Este enfoque no elimina las dependencias, como los permisos o las propiedades extendidas, y no es necesario copiar / pegar la lógica propensa a errores para hacerCREATE
/ALTER
en una sola declaración.Aquí está la plantilla que uso para crear o cambiar una función escalar. Lo dejaré como un ejercicio para que el lector adapte esto a otros tipos de objetos (procesos almacenados, disparadores, etc.).
fuente
GO
realmente garantiza que el script se romperá, yaIF
que no llevará a ninguna parte.DROP
/CREATE
editado. Gracias.Tiene la opción de verificar si el objeto existe en el
database
y crear si no:fuente