管理タスクの一部として、トリガを作成する必要がある多くのテーブルがあります。トリガは、オブジェクトが変更されたときに、監査データベースにフラグと日付を設定します。簡単にするために、トリガーを作成する必要があるすべてのオブジェクトを含む表があります。動的SQLエラー: 'CREATE TRIGGER'はクエリバッチの最初の文でなければなりません。
私は、各オブジェクトのためにこれを行うには、いくつかの動的SQLを生成しようとしていますが、私はこのエラーを取得しています:ここで
'CREATE TRIGGER' must be the first statement in a query batch.
は、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
私はPRINT
を使用して、新しいクエリウィンドウにコードを貼り付けた場合、コードは問題なく実行されます。
GO
ステートメントを削除しました。これもエラーを起こしていました。
私には何が欠けていますか?
EXEC(@sql);
またはEXEC sp_executesql @sql;
を使用してエラーが発生するのはなぜですか?
EXEC()
内のコンテキストと関連がありますか?
ご協力いただきありがとうございます。
これは本当にありがとうございます。上記の最初のオプションで、次のようにコードを2つに分割しました: – MarkusBee
[編集前のコメントにタイムアウトしました] ありがとうございました。私はあなたの最初のオプションで示唆しているように、コードを2つの '部分'に分割しました。最初の部分は完全に実行されます。 この手順は「監査」データベースから実行され、トリガーを必要とするオブジェクトは他のデータベースにあることを明確にします。 完全修飾テーブル名を使用していても、CREATE TRIGGERステートメントを実行すると、次のエラーがスローされるようになりました: "ターゲットが現在のデータベースにないため、[...]でトリガーを作成できません。 これを回避する方法はありますか?別のデータベースのコンテキスト内で実行するにはどうすればよいですか?おかげさまで – MarkusBee
@markb:私の更新を見てください。私はそれが欲しいと思うほどすべてが明確であるかどうか分からないので、躊躇しないでください。 –