Sql-Server

編寫數據庫中所有觸發器的腳本

  • April 25, 2018

我有一些數據庫作為訂閱者參與複製,它們有觸發器並被一組不同的應用程序使用。

每次我需要重新初始化這些數據庫時,我都需要編寫觸發器、權限和索引的腳本,應用快照,然後重新應用這些觸發器、索引和權限。

是否有一個腳本可以用來編寫目前數據庫的所有觸發器?

這似乎比您擁有的要簡單得多:

CREATE TABLE #tmp
(
 db          sysname,
 sch         sysname,
 obj         sysname,
 name        sysname,
 is_disabled bit,
 def         nvarchar(max)
);
GO

INSERT #tmp SELECT DB_NAME(), 
 s.name, o.name, t.name, 
 t.is_disabled, m.definition
FROM sys.triggers AS t
INNER JOIN sys.sql_modules AS m
ON t.object_id = m.object_id
INNER JOIN sys.objects AS o
ON t.parent_id = o.object_id
INNER JOIN sys.schemas AS s
ON o.schema_id = s.schema_id
WHERE parent_class = 1;

當您準備好再次創建它們時:

DECLARE @sql nvarchar(max) = N'';

SELECT @sql += def 
 + CHAR(13) + CHAR(10) + N'GO' 
 + CHAR(13) + CHAR(10) 
FROM #tmp;

SELECT @sql += N'DISABLE TRIGGER ' 
 + QUOTENAME(sch) + N'.' + QUOTENAME(name)
 + N' ON ' 
 + QUOTENAME(sch) + N'.' + QUOTENAME(obj) + N';'
FROM #tmp WHERE is_disabled = 1;

PRINT @sql;
-- EXEC sys.sp_executesql @sql;

是的,您將無法驗證整個腳本是否存在,因為 SSMS 不會輸出@sql. 有關解決方法,請參閱此文章

另外,如果您總是知道要影響的數據庫,我不知道為什麼需要將數據庫作為動態腳本的一部分,但是有一種更安全的方法可以使數據庫名稱動態化,而無需連接值並邀請 SQL 注入:

DECLARE @db sysname = N'AdventureWorks';

DECLARE @exec nvarchar(max), @sql nvarchar(max);

SET @exec = QUOTENAME(@db) + N'.sys.sp_executesql';

SET @sql = N'SELECT DB_NAME();';

EXEC @exec @sql;

引用自:https://dba.stackexchange.com/questions/204238