サブスクライバーとしてレプリケーションに関与しているデータベースがいくつかあり、それらにはトリガーがあり、別のアプリケーションセットで使用されています。
これらのデータベースを再初期化する必要があるたびに、トリガー、アクセス許可、およびインデックスをスクリプト化し、スナップショットを適用してから、これらのトリガー、インデックス、およびアクセス許可を再適用する必要があります。
現在のデータベースのすべてのトリガーをスクリプト化するために使用できるスクリプトはありますか?
これはあなたが持っているものよりもずっと簡単に見えます:
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;
以下のスクリプトを参考にしてください。
-- script all triggers of the current database
--marcelo miorelli
--17-april-2018
DECLARE @CHECK_IF_TRIGGER_EXISTS BIT = 1
SET NOCOUNT ON
SET DEADLOCK_PRIORITY LOW
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
IF OBJECT_ID('tempdb..#Radhe') IS NOT NULL
BEGIN
DROP TABLE #RADHE
END
CREATE TABLE #Radhe(
DB sysname not null,
parent_name nvarchar(600) not null,
object_id int not null,
trigger_name sysname not null,
is_disabled bit,
i int not null identity(1,1),
[trigger_definition] NVARCHAR(MAX) not null
);
DECLARE @object_id int;
DECLARE @SQL nvarchar(max);
DECLARE @theSQL nvarchar(max);
declare @DB sysname
declare @parent_name nvarchar(600)
declare @trigger_name sysname
declare @is_disabled bit
select @DB = db_name(db_id())
--select @DB
SELECT @SQL =
'-------------------------------------------------------------------------------------------------------------------
DECLARE
@olddelim nvarchar(32) = char(13) + Char(10),
@newdelim nchar(1) = NCHAR(9999); -- pencil (✏)
SELECT the_db_name = quotename(db_name(db_id()))
,parent_name = @parent_name
,the_object_id = @obj_id
,trigger_name = @trigger_name
,is_disabled = @is_disabled
,trigger_definition = [Value]
FROM master.dbo.splitstring(OBJECT_DEFINITION(@obj_id), @olddelim);
-------------------------------------------------------------------------------------------------------------------';
-- PRINT @SQL
BEGIN TRY
DECLARE the_triggers CURSOR STATIC LOCAL FORWARD_ONLY READ_ONLY
FOR
SELECT
object_id=s.object_id
,parent_name = QUOTENAME(OBJECT_SCHEMA_NAME(s.parent_id)) + '.' + QUOTENAME(OBJECT_NAME(s.parent_id))
,trigger_name = QUOTENAME(OBJECT_SCHEMA_NAME(s.object_id)) + '.' + QUOTENAME(OBJECT_NAME(s.object_id))
,s.is_disabled
FROM sys.triggers s
WHERE 1=1
OPEN the_triggers;
FETCH NEXT FROM the_triggers
INTO @object_id,@parent_name,@trigger_name,@is_disabled;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @theSQL = 'EXEC ' + QUOTENAME(@DB) +
'.sys.sp_executesql @SQL' + CHAR(10) +
',N''@obj_id int,@parent_name nvarchar(600),@trigger_name sysname,@is_disabled bit'',' + CHAR(10) +
'''' + CAST (@object_id as nvarchar) + '''' + ',' +
'''' + @parent_name + '''' + ',' +
'''' + @trigger_name + '''' + ',' +
'''' + CAST (COALESCE(@is_disabled,0) as nvarchar) +
'''' +';' + CHAR(10)
-------------------------------------------
-- when @CHECK_IF_TRIGGER_EXISTS is on
-- add code that checks whether the trigger exists
-- and if it does drop it
-------------------------------------------
if @CHECK_IF_TRIGGER_EXISTS = 1
BEGIN
INSERT INTO #Radhe(DB,parent_name,object_id,trigger_name,is_disabled,trigger_definition) values
(QUOTENAME(db_name()),@parent_name,@object_id,@trigger_name,@is_disabled,'GO')
INSERT INTO #Radhe(DB,parent_name,object_id,trigger_name,is_disabled,trigger_definition) values
(QUOTENAME(db_name()),@parent_name,@object_id,@trigger_name,@is_disabled,'use ' + QUOTENAME(db_name()))
INSERT INTO #Radhe(DB,parent_name,object_id,trigger_name,is_disabled,trigger_definition) values
(QUOTENAME(db_name()),@parent_name,@object_id,@trigger_name,@is_disabled,'GO')
INSERT INTO #Radhe(DB,parent_name,object_id,trigger_name,is_disabled,trigger_definition) values
(QUOTENAME(db_name()),@parent_name,@object_id,@trigger_name,@is_disabled,'if OBJECT_ID('+ '''' + @trigger_name + '''' + ') is not null')
INSERT INTO #Radhe(DB,parent_name,object_id,trigger_name,is_disabled,trigger_definition) values
(QUOTENAME(db_name()),@parent_name,@object_id,@trigger_name,@is_disabled,' drop trigger '+ @trigger_name + ' ')
INSERT INTO #Radhe(DB,parent_name,object_id,trigger_name,is_disabled,trigger_definition) values
(QUOTENAME(db_name()),@parent_name,@object_id,@trigger_name,@is_disabled,'GO')
END
-------------------------------------------
-- do the insert here
-- the trigger source code
-------------------------------------------
--print @theSQL
INSERT INTO #Radhe(DB,parent_name,object_id,trigger_name,is_disabled,trigger_definition)
EXEC sys.sp_executesql @theSQL
, N'@SQL nvarchar(max) '
, @SQL = @sql
-- add a GO after the trigger definition
INSERT INTO #Radhe(DB,parent_name,object_id,trigger_name,is_disabled,trigger_definition) values
(QUOTENAME(db_name()),@parent_name,@object_id,@trigger_name,@is_disabled,'GO')
-- fetch the next trigger
FETCH NEXT FROM the_triggers
INTO @object_id,@parent_name,@trigger_name,@is_disabled;
END
-------------------------------------------
BEGIN TRY
--clean it up
CLOSE the_triggers;
DEALLOCATE the_triggers;
END TRY
BEGIN CATCH
--do nothing
END CATCH
-------------------------------------------
END TRY
BEGIN CATCH
-------------------------------------------
BEGIN TRY
--clean it up
CLOSE the_triggers;
DEALLOCATE the_triggers;
END TRY
BEGIN CATCH
--do nothing
END CATCH
-------------------------------------------
DECLARE @ERRORMESSAGE NVARCHAR(512),
@ERRORSEVERITY INT,
@ERRORNUMBER INT,
@ERRORSTATE INT,
@ERRORPROCEDURE SYSNAME,
@ERRORLINE INT,
@XASTATE INT
SELECT
@ERRORMESSAGE = ERROR_MESSAGE(),
@ERRORSEVERITY = ERROR_SEVERITY(),
@ERRORNUMBER = ERROR_NUMBER(),
@ERRORSTATE = ERROR_STATE(),
@ERRORPROCEDURE = ERROR_PROCEDURE(),
@ERRORLINE = ERROR_LINE()
SET @ERRORMESSAGE =
(
SELECT CHAR(13) +
'Message:' + SPACE(1) + @ErrorMessage + SPACE(2) + CHAR(13) +
'Error:' + SPACE(1) + CONVERT(NVARCHAR(50),@ErrorNumber) + SPACE(1) + CHAR(13) +
'Severity:' + SPACE(1) + CONVERT(NVARCHAR(50),@ErrorSeverity) + SPACE(1) + CHAR(13) +
'State:' + SPACE(1) + CONVERT(NVARCHAR(50),@ErrorState) + SPACE(1) + CHAR(13) +
'Routine_Name:' + SPACE(1) + COALESCE(@ErrorProcedure,'') + SPACE(1) + CHAR(13) +
'Line:' + SPACE(1) + CONVERT(NVARCHAR(50),@ErrorLine) + SPACE(1) + CHAR(13) +
'Executed As:' + SPACE(1) + SYSTEM_USER + SPACE(1) + CHAR(13) +
'Database:' + SPACE(1) + DB_NAME() + SPACE(1) + CHAR(13) +
'OSTime:' + SPACE(1) + CONVERT(NVARCHAR(25),CURRENT_TIMESTAMP,121) + CHAR(13)
)
--We can also save the error details to a table for later reference here.
RAISERROR (@ERRORMESSAGE,16,1)
END CATCH
SELECT * FROM #RADHE