Come parte di alcune attività amministrative, abbiamo molti tavoli che ogni bisogno di un innesco creato. Il trigger imposta un flag e la data nel database Audit quando un oggetto è stato modificato. Per semplicità, ho una tabella con tutti gli oggetti che hanno bisogno di trigger creati.dinamica degli errori di SQL: 'CREATE TRIGGER' deve essere la prima istruzione in un batch di query
Sto cercando di generare un certo SQL dinamico per fare questo per ogni oggetto, ma sto ottenendo questo errore:
'CREATE TRIGGER' must be the first statement in a query batch.
Ecco il codice per generare il codice SQL.
CREATE PROCEDURE [spCreateTableTriggers]
AS
BEGIN
DECLARE @dbname varchar(50),
@schemaname varchar(50),
@objname varchar(150),
@objtype varchar(150),
@sql nvarchar(max),
@CRLF varchar(2)
SET @CRLF = CHAR(13) + CHAR(10);
DECLARE ObjectCursor CURSOR FOR
SELECT DatabaseName,SchemaName,ObjectName
FROM Audit.dbo.ObjectUpdates;
SET NOCOUNT ON;
OPEN ObjectCursor ;
FETCH NEXT FROM ObjectCursor
INTO @dbname,@schemaname,@objname;
WHILE @@FETCH_STATUS=0
BEGIN
SET @sql = N'USE '+QUOTENAME(@dbname)+'; '
SET @sql = @sql + N'IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'''+QUOTENAME(@schemaname)+'.[Tiud_'[email protected]+'_AuditObjectUpdates]'')) '
SET @sql = @sql + N'BEGIN DROP TRIGGER '+QUOTENAME(@schemaname)+'.[Tiud_'[email protected]+'_AuditObjectUpdates]; END; '+[email protected]
SET @sql = @sql + N'CREATE TRIGGER '+QUOTENAME(@schemaname)+'.[Tiud_'[email protected]+'_AuditObjectUpdates] '[email protected]
SET @sql = @sql + N' ON '+QUOTENAME(@schemaname)+'.['[email protected]+'] '[email protected]
SET @sql = @sql + N' AFTER INSERT,DELETE,UPDATE'[email protected]
SET @sql = @sql + N'AS '[email protected]
SET @sql = @sql + N'IF EXISTS(SELECT * FROM Audit.dbo.ObjectUpdates WHERE DatabaseName = '''[email protected]+''' AND ObjectName = '''[email protected]+''' AND RequiresUpdate=0'[email protected]
SET @sql = @sql + N'BEGIN'[email protected]
SET @sql = @sql + N' SET NOCOUNT ON;'[email protected]
SET @sql = @sql + N' UPDATE Audit.dbo.ObjectUpdates'[email protected]
SET @sql = @sql + N' SET RequiresUpdate = 1'[email protected]
SET @sql = @sql + N' WHERE DatabaseName = '''[email protected]+''' '[email protected]
SET @sql = @sql + N' AND ObjectName = '''[email protected]+''' '[email protected]
SET @sql = @sql + N'END' [email protected]
SET @sql = @sql + N'ELSE' [email protected]
SET @sql = @sql + N'BEGIN' [email protected]
SET @sql = @sql + N' SET NOCOUNT ON;' [email protected]
SET @sql = @sql + @CRLF
SET @sql = @sql + N' -- Update ''SourceLastUpdated'' date.'[email protected]
SET @sql = @sql + N' UPDATE Audit.dbo.ObjectUpdates'[email protected]
SET @sql = @sql + N' SET SourceLastUpdated = GETDATE() '[email protected]
SET @sql = @sql + N' WHERE DatabaseName = '''[email protected]+''' '[email protected]
SET @sql = @sql + N' AND ObjectName = '''[email protected]+''' '[email protected]
SET @sql = @sql + N'END; '[email protected]
--PRINT(@sql);
EXEC sp_executesql @sql;
FETCH NEXT FROM ObjectCursor
INTO @dbname,@schemaname,@objname;
END
CLOSE ObjectCursor ;
DEALLOCATE ObjectCursor ;
END
Se uso PRINT
e incollare il codice per una nuova finestra di query, il codice viene eseguito senza alcun problema.
ho rimosso i GO
dichiarazioni come questo è stato anche dà errori.
Cosa mi manca?
Perché ricevo un errore utilizzando EXEC(@sql);
o addirittura EXEC sp_executesql @sql;
?
Si tratta di qualcosa che ha a che fare con il contesto all'interno di EXEC()
?
Molte grazie per qualsiasi aiuto.
Mille grazie per questo. Ora ho diviso il codice in due "pezzi" come suggerito nella prima opzione sopra riportata, come segue: – MarkusBee
[EDIT scaduto nel commento precedente.] Molte grazie. Ho diviso il codice in due "pezzi" come suggerisci nella tua prima opzione. La prima parte viene eseguita perfettamente. Spiegherò che la procedura viene eseguita dal database 'Audit' e gli oggetti che richiedono trigger si trovano in altri database. L'esecuzione dell'istruzione 'CREATE TRIGGER' ora genera il seguente errore, anche quando si utilizza il nome completo della tabella: " Impossibile creare trigger su [...] poiché la destinazione non si trova nel database corrente. " C'è un modo per aggirare questo? Come posso farlo eseguire nel contesto di un altro database? Grazie. – MarkusBee
@markb: vedere il mio aggiornamento. Non sono sicuro che tutto sia chiaro come vorrei, quindi non esitare a chiedere. –