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?

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top