Se você usar o SSMS (ou outra ferramenta semelhante) para executar o código produzido por este script, você obterá exatamente o mesmo erro. Pode funcionar bem quando você insere delimitadores de lote (
GO ), mas agora que não, você também enfrentará o mesmo problema no SSMS. Por outro lado, a razão pela qual você não pode colocar
GO em seus scripts dinâmicos é porque GO não é uma instrução SQL, é apenas um delimitador reconhecido pelo SSMS e algumas outras ferramentas. Provavelmente você já está ciente disso. De qualquer forma, o ponto de
GO é para a ferramenta saber que o código deve ser dividido e suas partes executadas separadamente . E isso, separadamente , é o que você deve fazer em seu código também. Então, você tem essas opções:
-
insiraEXEC sp_execute @sqllogo após a parte que descarta o gatilho, redefina o valor de@sqlpara então armazenar e executar a parte de definição por sua vez;
-
use duas variáveis,@sql1e@sql2, armazene a parte IF EXISTS/DROP em@sql1, o CREATE TRIGGER em@sql2, execute os dois scripts (novamente, separadamente).
Mas então, como você já descobriu, você enfrentará outro problema:você não pode criar um gatilho em outro banco de dados sem executar a instrução no contexto desse banco de dados .
Agora, existem 2 maneiras de fornecer o contexto necessário:
1) use um
USE declaração; 2) execute a(s) instrução(ões) como uma consulta dinâmica usando
EXEC targetdatabase..sp_executesql N'…' . Obviamente, a primeira opção não funcionará aqui:não podemos adicionar
USE … antes de CREATE TRIGGER , porque o último deve ser a única instrução no lote. A segunda opção pode ser usado, mas exigirá uma camada adicional de dinamicidade (não tenho certeza se é uma palavra). É porque o nome do banco de dados é um parâmetro aqui e, portanto, precisamos executar o
EXEC targetdatabase..sp_executesql N'…' como um script dinâmico e, como o script real a ser executado deve ser um script dinâmico, ele será aninhado duas vezes. Então, antes do (segundo)
EXEC sp_executesql @sql; linha adicione o seguinte:SET @sql = N'EXEC ' + @dbname + '..sp_executesql N'''
+ REPLACE(@sql, '''', '''''') + '''';
Como você pode ver, para integrar o conteúdo de
@sql como um script dinâmico aninhado corretamente, eles devem ser colocados entre aspas simples. Pela mesma razão, todas as aspas simples em @sql deve ser duplicado (por exemplo, usando o REPLACE() função
, como na afirmação acima).