Pokud používáte SSMS (nebo jiný podobný nástroj) ke spuštění kódu vytvořeného tím skript, dostanete přesně stejnou chybu. Mohlo by to běžet v pořádku, když vložíte oddělovače dávek (GO
), ale teď, když to neuděláte, budete čelit stejnému problému i v SSMS.
Na druhou stranu, důvod, proč nemůžete vložit GO
ve vašich dynamických skriptech je to proto, že GO
není SQL příkaz, je to pouze oddělovač rozpoznávaný SSMS a některými dalšími nástroji. Pravděpodobně jste si toho již vědomi.
Každopádně smyslem GO
je pro nástroj, aby věděl, že kód by měl být rozdělen a jeho části běžet odděleně . A to samostatně , je to, co byste měli udělat i ve svém kódu.
Máte tedy tyto možnosti:
-
vložte
EXEC sp_execute @sql
hned za částí, která spouští spoušť, potom resetujte hodnotu@sql
poté uložit a spustit definiční část ve svém tahu; -
použijte dvě proměnné,
@sql1
a@sql2
, uložte část IF EXISTS/DROP do@sql1
, CREATE TRIGGER jeden do@sql2
a poté spusťte oba skripty (opět samostatně).
Ale pak, jak jste již zjistili, budete čelit dalšímu problému:nemůžete vytvořit spouštěč v jiné databázi bez spuštění příkazu v kontextu této databáze .
Nyní existují 2 způsoby, jak poskytnout potřebný kontext:
1) použijte USE
prohlášení;
2) spusťte příkaz(y) jako dynamický dotaz pomocí EXEC targetdatabase..sp_executesql N'…'
.
Je zřejmé, že první možnost zde nebude fungovat:nemůžeme přidat USE …
před CREATE TRIGGER
, protože druhý příkaz musí být jediným příkazem v dávce.
Druhá možnost může použít, ale bude to vyžadovat další vrstvu dynamiky (nejsem si jistý, jestli je to slovo). Je to proto, že název databáze je zde parametrem, a proto musíme spustit EXEC targetdatabase..sp_executesql N'…'
jako dynamický skript, a protože skutečný skript, který se má spustit, má být sám o sobě dynamickým skriptem, bude proto vnořen dvakrát.
Tedy před (druhým) EXEC sp_executesql @sql;
řádek přidejte následující:
SET @sql = N'EXEC ' + @dbname + '..sp_executesql N'''
+ REPLACE(@sql, '''', '''''') + '''';
Jak můžete vidět, integrovat obsah @sql
jako správně vnořený dynamický skript musí být uzavřeny v jednoduchých uvozovkách. Ze stejného důvodu jsou všechny uvozovky v @sql
musí být zdvojnásobeno (např. pomocí REPLACE()
funkce
, jako ve výše uvedeném prohlášení).