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 @sql
logo após a parte que descarta o gatilho, redefina o valor de@sql
para então armazenar e executar a parte de definição por sua vez;
-
use duas variáveis,@sql1
e@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).