シナリオ:
SQL Server DBAまたは開発者として作業しており、SQL Serverデータベースの1つで変更データキャプチャを有効にしました。CDCを有効にした後、AUDITまたはHISTビューを作成するため、変更されたレコードを取得できます。解決策:
以下のスクリプトは、データベースでCDCが有効になっているテーブルごとにビューを作成します。スクリプトを実行する前に監査スキーマを使用しました。監査スキーマを作成する必要があります。または、履歴スキーマでビューを作成する場合は、次のように変更します。監査から履歴までの以下のコードのスキーマ。各ビューは、列の下に戻ります
- Commit_Time、
- Colon_Name、
- Old_Value、
- New_Value、
- ModifiedBy
IF OBJECT_ID(N'tempdb..##CDC_TableList') IS NOT NULL
BEGIN DROP TABLE ##CDC_TableList
END SELECT T.name AS TableName, C.name AS ColumnName, 'CASE WHEN (sys.Fn_cdc_is_bit_set (sys.Fn_cdc_get_column_ordinal (''dbo_' + T.name + ''',''' + C.name+ + '''),__$update_mask) = 1) THEN Cast(' + C.Name + ' AS SQL_VARIANT) ELSE NULL END AS ' + C.name AS CaseStm INTO ##CDC_TableList
FROM sys.tables T INNER JOIN sys.columns c ON T.OBJECT_ID = c.OBJECT_ID
WHERE is_tracked_by_cdc = 1 AND c.is_identity = 0 AND C.name NOT IN ( 'CreatedBy', 'CreatedDate', 'ModifiedBy', 'ModifiedDate' ) AND T.TYPE='U' AND T.is_ms_shipped<>1 -- Select * from sys.tables DECLARE @TableName NVARCHAR(200)
DECLARE cdc_cursor CURSOR FOR SELECT DISTINCT TableName FROM ##CDC_TableList
OPEN cdc_cursor
FETCH NEXT FROM cdc_cursor INTO @TableName WHILE @@FETCH_STATUS = 0
BEGIN DECLARE @ColumnList NVARCHAR(MAX)
DECLARE @CaseStmList NVARCHAR(MAX)
DECLARE @SQL_Stm NVARCHAR(MAX)
DECLARE @SQL_Stm_DropView NVARCHAR(MAX)
PRINT @TableName SELECT @ColumnList = STUFF(o.COLUMNNAME, 1, 1, '') FROM ##CDC_TableList t CROSS APPLY (SELECT ',' + ColumnName+CHAR(10) AS [text()] FROM ##CDC_TableList c WHERE c.TableName = t.TableName FOR XML PATH('')) o (COLUMNNAME) WHERE t.TableName=@TableName PRINT @ColumnList SELECT @CaseStmList = STUFF(o.COLUMNNAME, 1, 1, '') FROM ##CDC_TableList t CROSS APPLY (SELECT ',' + CaseStm+CHAR(10) AS [text()] FROM ##CDC_TableList c WHERE c.TableName = t.TableName FOR XML PATH('')) o (COLUMNNAME) WHERE t.TableName=@TableName --PRINT @CaseStmList --If using Other Schema than AUDIT THEN change to that. SET @SQL_Stm=' CREATE VIEW AUDIT.vw_'+@TableName+' AS SELECT sys.Fn_cdc_map_lsn_to_time(up_b.__$start_lsn) AS Commit_Time, up_b.Column_Name, up_b.Old_Value, up_a.New_Value,up_a.ModifiedBy FROM ( SELECT __$start_lsn, column_name, old_value,ModifiedBy FROM (SELECT __$start_lsn,'+@CaseStmList+',ModifiedBy FROM cdc.fn_cdc_get_all_changes_dbo_'+@TableName+'( sys.fn_cdc_get_min_lsn(''dbo_'+@TableName+'''), sys.fn_cdc_map_time_to_lsn(''largest less than or equal'',GETDATE()), N''all update old'') WHERE __$operation = 3 ) AS BeforeUpdate UNPIVOT (old_value FOR column_name IN ('+@ColumnList+') ) AS unp) AS up_b INNER JOIN (SELECT __$start_lsn, column_name, new_value,ModifiedBy FROM (SELECT __$start_lsn,'+@CaseStmList+',ModifiedBy FROM cdc.fn_cdc_get_all_changes_dbo_'+@TableName+'(sys.fn_cdc_get_min_lsn(''dbo_'+@TableName+'''), sys.fn_cdc_map_time_to_lsn(''largest less than or equal'',GETDATE()), N''all'') WHERE __$operation = 4 ) AS AfterUpdate UNPIVOT (new_value FOR column_name IN ('+@ColumnList+') ) AS unp ) AS up_a ON up_b.__$start_lsn = up_a.__$start_lsn AND up_b.column_name = up_a.column_name' --Drop View if already exists SET @SQL_Stm_DropView= 'IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = ''vw_'+@TableName+''') DROP VIEW AUDIT.vw_'+@TableName PRINT @SQL_Stm_DropView EXEC (@SQL_Stm_DropView)
EXEC ( @SQL_Stm)
FETCH NEXT FROM cdc_cursor INTO @TableName
END CLOSE cdc_cursor DEALLOCATE cdc_cursor