Eu tenho um procedimento simples que existe em mais de 150 bancos de dados. Eu posso excluí-los um por um, que é o trabalho mais estúpido a se fazer no mundo do desenvolvimento de software. Ou posso de alguma forma excluí-los dinamicamente em uma consulta, o que é inteligente, mas não funciona.
Eu tentei:
execute sp_msforeachdb 'drop procedure Usages'
Eu obtive:
Não é possível descartar o procedimento 'Usages', porque ele não existe ou você não tem permissão.
Então pensei que talvez eu criasse um cursor para isso. Assim escrevi:
declare @command nvarchar(max) = '
drop procedure Usages
';
declare @databaseName nvarchar(100)
declare databasesCursor cursor for select [name] from sys.databases where database_id > 5
open databasesCursor
fetch next from databasesCursor into @databaseName
while @@fetch_status = 0
begin
print @databaseName
execute sp_executesql @command
fetch next from databasesCursor into @databaseName
end
close databasesCursor
deallocate databasesCursor
Mais uma vez, recebi a mesma mensagem. Eu pensei, talvez isso não mude o contexto do banco de dados, então eu prefixei o comando delete com o nome do banco de dados fornecido, para que os comandos se tornassem semelhantes a drop procedure [SomeDatabase].dbo.Usages
, mas recebi:
'DROP PROCEDURE' não permite especificar o nome do banco de dados como um prefixo para o nome do objeto.
Então, eu descobri para executar dinamicamente use @databaseName
para que eu possa descartar o procedimento no contexto desse banco de dados. Mas não está funcionando. O que devo fazer? Estou preso ao método inteligente e passei mais tempo do que o método estúpido agora.
Você estava muito perto, mas esqueceu uma coisinha:
O uso [?] realmente irá para cada db e o executará lá, isso deve resolver seu problema.
No entanto, você pode adicionar algo que primeiro verifique se o procedimento existe antes de eliminá-lo, porque agora você ainda receberá o erro se ele não existir no banco de dados.
Edit: Uma versão mais limpa seria esta:
Ele verificará se existe antes de cair, então se houver tal sp, não lhe dará um erro.
EDIT2: ElliotMajor fez o comentário
E ele está certo sobre isso. Para o que você está fazendo agora, deve estar tudo bem, mas se você precisar colocar isso em algum código de produção, há algumas substituições para este sp.
Versões melhoradas por: Spaghetti DBA e Aaron Bertrand
Faltam algumas informações, qual versão do SQL Server você está usando? Quais permissões você tem?
Dito isso, acho que o código abaixo deve funcionar, testei no SQL 2019.
Isso cria uma consulta para cada instrução drop, em seguida, executa cada uma e a executa (e imprime o erro se falhar)
Você pode alterar o
EXEC (@query)
paraPRINT @Query
se quiser apenas as instruções ou se livrar do LOOP e apenasSELECT * FROM #querytable