If you use SSMS (or another similar tool) to run the code generated by this script, you will get exactly the same error. When batch separators ( GO ) are enabled, it may work fine, but now that you do not, you will encounter the same problem in SSMS too.
On the other hand, the reason you cannot put GO in your dynamic scripts is because GO not an SQL statement, but simply a delimiter recognized by SSMS and some other tools. You may already know about this.
In any case, the GO point is designed to let the tool know that the code should be split, and its parts are executed separately. And this is separate, this is what you should do in your code.
So, you have the following options:
insert EXEC sp_execute @sql immediately after the part that resets the trigger, then reset the @sql value to then save and run the definition part in turn;
use two variables, @sql1 and @sql2 , save the IF EXISTS / DROP part to @sql1 , CREATE TRIGGER one in @sql2 , then run both scripts (again, separately).
But then, as you already found out, you will encounter another problem: you cannot create a trigger in another database without running the instruction in the context of this database.
Now there are two ways to provide the necessary context:
1) use the USE instruction;
2) run the statement as a dynamic query using EXEC targetdatabase ..sp_executesql N'β¦' .
Obviously, the first option will not work here: we cannot add USE β¦ until CREATE TRIGGER , because the latter should be the only statement in the package.
You can use the second option, but this will require an additional level of dynamism (not sure if this word). This is because here the database name is a parameter, so we need to run EXEC targetdatabase ..sp_executesql N'β¦' as a dynamic script, and since the actual script itself needs to be a dynamic script, it will therefore be nested twice.
So, before the line (second) EXEC sp_executesql @sql; add the following:
SET @sql = N'EXEC ' + @dbname + '..sp_executesql N''' + REPLACE(@sql, '''', '''''') + '''';
As you can see, to properly include the contents of @sql as a nested dynamic script, they must be enclosed in single quotes. For the same reason, every single quote in @sql should be doubled (for example, using the REPLACE() function , as in the statement above).