Om du använder SSMS (eller annat liknande verktyg) för att köra koden som produceras av denna skriptet får du exakt samma fel. Det kunde fungera bra när du infogade batchavgränsare (GO
), men nu när du inte gör det kommer du att möta samma problem i SSMS också.
Å andra sidan, anledningen till att du inte kan lägga GO
i dina dynamiska skript beror på att GO
är inte en SQL-sats, det är bara en avgränsare som känns igen av SSMS och några andra verktyg. Förmodligen är du redan medveten om det.
Hur som helst, poängen med GO
är för verktyget att veta att koden ska delas och dess delar köras separat . Och det, separat , är vad du bör göra i din kod också.
Så du har dessa alternativ:
-
infoga
EXEC sp_execute @sql
precis efter den del som släpper utlösaren, återställ sedan värdet på@sql
för att sedan lagra och köra definitionsdelen i sin tur; -
använd två variabler,
@sql1
och@sql2
, lagra IF EXISTS/DROP-delen i@sql1
, CREATE TRIGGER-en till@sql2
, kör sedan båda skripten (igen, separat).
Men sedan, som du redan har fått reda på, kommer du att ställas inför ett annat problem:du kan inte skapa en utlösare i en annan databas utan att köra satsen i sammanhanget för den databasen .
Nu finns det två sätt att tillhandahålla det nödvändiga sammanhanget:
1) använd en USE
uttalande;
2) kör satsen/satserna som en dynamisk fråga med EXEC targetdatabase..sp_executesql N'…'
.
Uppenbarligen kommer det första alternativet inte att fungera här:vi kan inte lägga till USE …
före CREATE TRIGGER
, eftersom det senare måste vara det enda uttalandet i partiet.
Det andra alternativet kan användas, men det kommer att kräva ett extra lager av dynamik (osäker på om det är ett ord). Det beror på att databasnamnet är en parameter här och därför måste vi köra EXEC targetdatabase..sp_executesql N'…'
som ett dynamiskt skript, och eftersom det faktiska skriptet som ska köras i sig är tänkt att vara ett dynamiskt skript, kommer det därför att kapslas två gånger.
Så före (andra) EXEC sp_executesql @sql;
rad lägg till följande:
SET @sql = N'EXEC ' + @dbname + '..sp_executesql N'''
+ REPLACE(@sql, '''', '''''') + '''';
Som du kan se, för att integrera innehållet i @sql
som ett kapslat dynamiskt skript på rätt sätt måste de omges av enkla citattecken. Av samma anledning, varenda citattecken in @sql
måste fördubblas (t.ex. med REPLACE()
funktion
, som i ovanstående uttalande).