Como crio condicionalmente um procedimento armazenado no SQL Server?
-
09-06-2019 - |
Pergunta
Como parte da minha estratégia de integração, tenho alguns scripts SQL executados para atualizar o banco de dados.A primeira coisa que todos esses scripts fazem é verificar se eles precisam ser executados, por exemplo:
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 bem!Exceto se eu precisar adicionar um procedimento armazenado.O comando “create proc” deve ser o único comando em um lote de comandos SQL.Colocar um "create proc" na minha instrução IF causa este erro:
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
Ai!Como coloco o comando CREATE PROC no meu script e faço com que ele seja executado apenas se necessário?
Solução
Aqui está o que eu descobri:
Envolva-o em um EXEC(), assim:
if @version <> @expects
begin
...snip...
end
else
begin
exec('CREATE PROC MyProc AS SELECT ''Victory!''');
end
Funciona como um encanto!
Outras dicas
SET NOEXEC ON é uma boa maneira de desligar alguma parte do 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 aqui:https://codereview.stackexchange.com/questions/10490/conditional-create-must-be-the-only-statement-in-the-batch
P.S.Outra maneira é definida parseon {on | DESLIGADO }.
Mas tome cuidado com aspas simples em seu procedimento armazenado - elas precisam ser "escapadas" adicionando uma segunda.A primeira resposta fez isso, mas caso você tenha perdido.Uma armadilha para jovens jogadores.
Versionar seu banco de dados é o caminho a seguir, mas...Por que criar procedimentos armazenados condicionalmente.Para visualizações, procedimentos armazenados e funções, basta eliminá-los condicionalmente e recriá-los sempre.Se você criar condicionalmente, não limpará bancos de dados que tenham um problema ou um hack que foi instalado há 2 anos por outro desenvolvedor (você ou eu nunca faríamos isso) que tinha certeza de que se lembraria de remover o único vez atualização de emergência.
O problema ao descartar e criar é que você perde todas as concessões de segurança que foram aplicadas anteriormente ao objeto que está sendo descartado.
Devo admitir que normalmente concordaria com @Peter - eu descarto condicionalmente e depois recrio incondicionalmente todas as vezes.Já fui pego muitas vezes no passado ao tentar adivinhar as diferenças de esquema entre bancos de dados, com ou sem qualquer forma de controle de versão.
Dito isto, sua sugestão @Josh é muito legal.Certamente interessante.:-)
Este é um tópico antigo, mas Jobo está incorreto:Criar procedimento deve ser a primeira instrução de um lote.Portanto, você não pode usar Exists
para testar a existência e depois usar Create
ou Alter
.Pena.
Minha solução é verificar se o proc existe, em caso afirmativo, descarte-o e crie o proc (mesma resposta do @robsoft, mas com um exemplo ...)
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 o comando 'Exists' no T-SQL para ver se o processo armazenado existe.Se isso acontecer, use 'Alter', caso contrário, use 'Create'
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