Atualização de janeiro de 2017 - SQL Server 2016+ / Banco de Dados SQL do Azure
O SQL Server 2016 e a versão atual do Banco de Dados SQL do Azure agora têm a seguinte sintaxe para funções, procedimentos, tabelas, bancos de dados etc. ( DROP IF EXISTS
):
DROP FUNCTION IF EXISTS dbo.fn_myfunc;
E o SQL Server 2016 Service Pack 1 adiciona funcionalidades ainda melhores aos módulos (funções, procedimentos, gatilhos, exibições), o que significa que não há perda de permissões ou dependências ( CREATE OR ALTER
):
CREATE OR ALTER FUNCTION dbo.fn_myfunc ...
Ambos os aprimoramentos de sintaxe podem levar a scripts muito mais simples usados para controle de origem, implantações etc.
Mas, se você estiver usando ...
versões mais antigas
Você precisa fazer o que o SQL Server faz ao criar um script no 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
Ou você pode dizer:
BEGIN TRY
DROP FUNCTION dbo.fn_myfunc;
END TRY
BEGIN CATCH
PRINT 'Function did not exist.';
END CATCH
GO
CREATE FUNCTION...
Ou você pode apenas dizer:
DROP FUNCTION dbo.fn_myfunc;
GO
CREATE FUNCTION...
(Aqui você receberá uma mensagem de erro se a função ainda não existir, mas o script continuará a partir do próximo GO, portanto, se a queda funcionou ou não, a função ainda será (re) criada.)
Observe que, se você soltar a função e recriá-la, também perderá permissões e informações potencialmente sobre dependência.
O erro é bastante auto-explicativo. Existem algumas maneiras de corrigi-lo.
Separe o script em lotes diferentes no Management Studio usando a
GO
pseudo-palavra-chave eDROP
/CREATE
o objeto. (Observe que a própria palavra-chave pode ser alterada nas opções do Management Studio, mas essa é a configuração de fato, por isso sugiro deixá-la em paz).Quando você executa um script (ou a parte selecionada de um script), o Management Studio separa cada parte do script entre
GO
s e envia seqüencialmente as partes para o SQL Server como lotes separados.Use SQL dinâmico para enviar um lote separado de outro lote.
Esse é o método preferencial, pois seu script não depende da funcionalidade externa para ser executado corretamente. Por exemplo, se seu aplicativo tiver um programa de atualização de banco de dados, geralmente ele carregará um arquivo de script e o executará no servidor de destino. Você precisará adicionar lógica para separar os lotes como o Management Studio (nota: repleta de riscos) ou gravar o script de forma que o script inteiro possa ser executado com sucesso como um único lote.
Como mencionado em outra resposta, você pode fazer um teste /
CREATE
usando esse método (ou alguma outra combinação deDROP
/CREATE
, etc.). O que eu prefiro fazer é criar um objeto stub se o objeto não existir e, em seguida, usarALTER <object>
para realmente criar ou alterar. Essa abordagem não elimina dependências, como permissões ou propriedades estendidas, e não é necessário copiar / colar uma lógica propensa a erros para executar oCREATE
/ALTER
em uma única instrução.Aqui está o modelo que eu uso para criar ou alterar uma função escalar. Vou deixar como um exercício para o leitor adaptar isso a outros tipos de objetos (procs armazenados, gatilhos, etc.).
fonte
GO
garante que o script será interrompido, poisIF
não levará a lugar algum.DROP
/CREATE
- editado. Obrigado.Você tem a opção de verificar se o objeto existe no
database
e criar se não:fonte