Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

динамична sql грешка:„CREATE TRIGGER“ трябва да бъде първият израз в пакета на заявката

Ако използвате SSMS (или друг подобен инструмент), за да стартирате кода, произведен от това скрипт, ще получите точно същата грешка. Може да работи добре, когато сте вмъкнали пакетни разделители (GO ), но сега, когато не го правите, ще се сблъскате със същия проблем и в SSMS.

От друга страна, причината, поради която не можете да поставите GO във вашите динамични скриптове е защото GO не е SQL израз, това е просто разделител, разпознат от SSMS и някои други инструменти. Вероятно вече сте наясно с това.

Както и да е, смисълът на GO е инструментът да знае, че кодът трябва да бъде разделен и неговите части да се изпълняват отделно . И това, отделно , е това, което трябва да направите и във вашия код.

И така, имате следните опции:

  • вмъкнете EXEC sp_execute @sql точно след частта, която изпуска тригера, след което нулирайте стойността на @sql за да съхрани и изпълни дефиниционната част на свой ред;

  • използвайте две променливи, @sql1 и @sql2 , съхранете частта IF EXISTS/DROP в @sql1 , този CREATE TRIGGER в @sql2 , след което изпълнете и двата скрипта (отново поотделно).

Но след това, както вече разбрахте, ще се сблъскате с друг проблем:не можете да създадете тригер в друга база данни, без да изпълните оператора в контекста на тази база данни .

Сега има 2 начина за предоставяне на необходимия контекст:

1) използвайте USE изявление;

2) изпълнете израза(ите) като динамична заявка с помощта на EXEC targetdatabase..sp_executesql N'…' .

Очевидно първата опция няма да работи тук:не можем да добавим USE … преди CREATE TRIGGER , тъй като последният трябва да е единственият израз в пакета.

Втората опция може да се използва, но ще изисква допълнителен слой динамика (не съм сигурен дали е дума). Това е така, защото името на базата данни е параметър тук и затова трябва да изпълним EXEC targetdatabase..sp_executesql N'…' като динамичен скрипт и тъй като самият скрипт, който трябва да се изпълнява, се предполага, че е динамичен скрипт, той следователно ще бъде вложен два пъти.

И така, преди (втория) EXEC sp_executesql @sql; ред добавете следното:

SET @sql = N'EXEC ' + @dbname + '..sp_executesql N'''
           + REPLACE(@sql, '''', '''''') + '''';

Както можете да видите, за интегриране на съдържанието на @sql като правилно вложен динамичен скрипт, те трябва да бъдат оградени в единични кавички. По същата причина всяка една кавичка in @sql трябва да се удвои (напр. с помощта на REPLACE() функция , както в горното твърдение).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какво е доверена връзка?

  2. Намерете понеделници между 2 дати

  3. Създаване на потребител в база данни на Azure SQL с помощта на функции на Azure?

  4. Как да намерите низ в низ в SQL Server

  5. Конкатениране на много редове в един текстов низ с групиране