Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

dynamiczny błąd sql:„CREATE TRIGGER” musi być pierwszą instrukcją w partii kwerendy

Jeśli używasz programu SSMS (lub innego podobnego narzędzia) do uruchomienia kodu utworzonego przez to skrypt, otrzymasz dokładnie ten sam błąd. Może działać poprawnie po wstawieniu ograniczników partii (GO ), ale teraz, gdy tego nie zrobisz, napotkasz ten sam problem w SSMS.

Z drugiej strony powód, dla którego nie możesz umieścić GO w twoich dynamicznych skryptach jest to, że GO nie jest instrukcją SQL, jest jedynie ogranicznikiem rozpoznawanym przez SSMS i inne narzędzia. Prawdopodobnie już o tym wiesz.

W każdym razie punkt GO służy do tego, aby narzędzie wiedziało, że kod powinien zostać podzielony, a jego części uruchamiane oddzielnie . I to oddzielnie , jest to również to, co powinieneś zrobić w swoim kodzie.

Masz więc następujące opcje:

  • wstaw EXEC sp_execute @sql tuż po części, która upuszcza wyzwalacz, a następnie zresetuj wartość @sql aby następnie przechowywać i uruchamiać z kolei część definicji;

  • użyj dwóch zmiennych, @sql1 i @sql2 , zapisz część IF EXISTS/DROP w @sql1 , CREATE TRIGGER w @sql2 , a następnie uruchom oba skrypty (ponownie, osobno).

Ale potem, jak już się przekonałeś, staniesz przed innym problemem:nie możesz utworzyć wyzwalacza w innej bazie danych bez uruchomienia instrukcji w kontekście tej bazy danych .

Teraz istnieją 2 sposoby zapewnienia niezbędnego kontekstu:

1) użyj USE oświadczenie;

2) uruchom instrukcję(e) jako dynamiczne zapytanie za pomocą EXEC targetdatabase..sp_executesql N'…' .

Oczywiście pierwsza opcja nie zadziała tutaj:nie możemy dodać USE … przed CREATE TRIGGER , ponieważ ta ostatnia musi być jedyną instrukcją w partii.

Druga opcja może być używany, ale będzie wymagał dodatkowej warstwy dynamiczności (nie jestem pewien, czy to słowo). Dzieje się tak, ponieważ nazwa bazy danych jest tutaj parametrem i dlatego musimy uruchomić EXEC targetdatabase..sp_executesql N'…' jako skrypt dynamiczny, a ponieważ sam skrypt do uruchomienia powinien być skryptem dynamicznym, zostanie on zagnieżdżony dwukrotnie.

Tak więc przed (drugim) EXEC sp_executesql @sql; wiersz dodaj następujące:

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

Jak widać, zintegrować zawartość @sql jako poprawnie zagnieżdżony skrypt dynamiczny, muszą być ujęte w pojedyncze cudzysłowy. Z tego samego powodu każdy cudzysłów w @sql musi zostać podwojona (np. przy użyciu REPLACE() funkcja , jak w powyższym oświadczeniu).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Użyj NEWSEQUENTIALID(), aby utworzyć przyrostowy identyfikator GUID w SQL Server

  2. Jak zdrowy jest Twój serwer SQL? Proaktywne monitorowanie bazy danych ma kluczowe znaczenie

  3. mapowanie hibernacji datetimeoffset

  4. Powiadomienie o zmianach w SQL Server 2008

  5. Scal wartości wierszy w CSV (vel GROUP_CONCAT dla SQL Server)