作爲一些管理任務的一部分,我們有很多表,每個表都需要創建一個觸發器。當對象被修改時,觸發器將在審計數據庫中設置一個標誌和日期。爲了簡單起見,我有一個包含所有需要觸發器創建的對象的表格。動態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()
中的上下文有關?
非常感謝您的幫助。
非常感謝。我現在已經分裂代碼到兩個「片」爲你在第一個選項建議之上,如下所示:[編輯超時在以前的評論] – MarkusBee 2012-04-27 08:26:23
非常感謝。如您在第一個選項中所建議的那樣,我已將代碼分成兩部分。第一部分執行完美。 我將闡明該程序是從「審計」數據庫執行的,而需要觸發器的對象位於其他數據庫中。 現在Excecuting了'CREATE語句TRIGGER'引發以下錯誤,即使使用完全限定表名時: 「無法創建[...]作爲目標不在當前數據庫觸發器」。 有沒有辦法解決這個問題?我怎樣才能讓它在另一個數據庫的上下文中執行? 謝謝。 – MarkusBee 2012-04-27 08:37:51
@markb:請參閱我的更新。我不確定是否一切都如我所願,因此請不要猶豫,問。 – 2012-04-27 09:33:07