sql >> Database >  >> RDS >> Sqlserver

dynamische sql-fout:'CREATE TRIGGER' moet de eerste instructie in een querybatch zijn

Als u SSMS (of een ander soortgelijk hulpmiddel) gebruikt om de code uit te voeren die door dit is geproduceerd script, krijg je precies dezelfde fout. Het zou goed kunnen werken als u batchscheidingstekens invoegde (GO ), maar nu je dat niet doet, zul je hetzelfde probleem ook in SSMS tegenkomen.

Aan de andere kant, de reden waarom u GO . niet kunt plaatsen in uw dynamische scripts is omdat GO is geen SQL-instructie, het is slechts een scheidingsteken dat wordt herkend door SSMS en enkele andere tools. Waarschijnlijk weet je dat al.

Hoe dan ook, het punt van GO is dat de tool weet dat de code moet worden gesplitst en dat de delen ervan afzonderlijk moeten worden uitgevoerd . En dat, afzonderlijk , is wat u ook in uw code zou moeten doen.

Je hebt dus deze opties:

  • voeg EXEC sp_execute @sql in net na het deel dat de trigger laat vallen, reset dan de waarde van @sql om vervolgens het definitiegedeelte op zijn beurt op te slaan en uit te voeren;

  • gebruik twee variabelen, @sql1 en @sql2 , sla het IF EXISTS/DROP-gedeelte op in @sql1 , de CREATE TRIGGER een in @sql2 en voer vervolgens beide scripts uit (opnieuw, afzonderlijk).

Maar dan, zoals je al hebt ontdekt, krijg je te maken met een ander probleem:je kunt geen trigger maken in een andere database zonder de instructie in de context van die database uit te voeren .

Er zijn nu 2 manieren om de nodige context te bieden:

1) gebruik een USE verklaring;

2) voer de instructie(s) uit als een dynamische query met behulp van EXEC targetdatabase..sp_executesql N'…' .

Het is duidelijk dat de eerste optie hier niet werkt:we kunnen USE … niet toevoegen voor CREATE TRIGGER , omdat de laatste de enige verklaring in de batch moet zijn.

De tweede optie kan worden gebruikt, maar het vereist een extra laag dynamiek (weet niet of het een woord is). Het is omdat de databasenaam hier een parameter is en daarom moeten we EXEC targetdatabase..sp_executesql N'…' als een dynamisch script, en aangezien het eigenlijke script dat moet worden uitgevoerd zelf een dynamisch script moet zijn, wordt het daarom twee keer genest.

Dus, vóór de (tweede) EXEC sp_executesql @sql; regel voeg het volgende toe:

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

Zoals je kunt zien, om de inhoud van @sql te integreren als een genest dynamisch script correct is, moeten ze tussen enkele aanhalingstekens worden geplaatst. Om dezelfde reden is elk aanhalingsteken in @sql moet worden verdubbeld (bijvoorbeeld met behulp van de REPLACE() functie , zoals in de bovenstaande verklaring).



  1. ORA-04021:time-out opgetreden tijdens het wachten om object te vergrendelen

  2. MYSQL-query / datums ouder dan 1 week geleden (alle datumtijden in UTC)

  3. Een lijst met meerdere waarden invoegen in MySQL met behulp van pymysql

  4. De servertijdzonewaarde 'AEST' wordt niet herkend of vertegenwoordigt meer dan één tijdzone