Introduction
Added two new columns were to our source table while CDC was still enabled on the table. We need the new columns to appear in the CDC table but it will not start captureing.
Background
We are looking into enabling Sql Server Change Data Capture (CDC) for a new subsystem we are building.
We are being pushed for having a complete history traceability, and CDC would nicely solve this requirement with minimum effort on our scinario.
Did a small test where we created a table, enabled CDC for that table, and then added a new column to the table. Changes to the new column is not registered in the CDC table.
Is there a mechanism to update the CDC table to the new schema, and are there any best practices to how you deal with captured data when migrating the database schema?
Using the below code
I have recently started looking at CDC to do data auditing into application. I'm not an expert or DBA , but I think I did some research and have some answers for those problems.
CDC will help us achieve our goal of a completely traceable history, but I don't think it will get you all of the way that you look for audit. When CDC is turned ON against a table and the underlying table schema changes, such as adding/removing a column, changing datatype etc., these changes are not captured in the CDC table. Below are the steps on how to capture these new changes.
In summary, we have to copy the data from the CDC table to a temp table and after re-enabling CDC on the updated table, assign the correct __$start_lsn
in the cdc.change_tables
DECLARE @sql VARCHAR(8000)
DECLARE @tblName VARCHAR(100)
DECLARE @colname VARCHAR(100)
DECLARE @dbType VARCHAR(100)
DECLARE @cdcInst VARCHAR(100)
DECLARE @cdctblName VARCHAR(100)
DECLARE @cdcTemptblName VARCHAR(100)
SET @tblName = 'customer'
SET @cdcInst = 'dbo_' + @tblName
SET @cdctblName = 'cdc.dbo_' + @tblName + '_CT'
SET @cdcTemptblName = 'cdc.dbo_' + @tblName + '_Temp'
SET @colname = 'OfficePhoneNum'
SET @dbType = 'varchar(50)'
SET @sql = 'SELECT * INTO ' + @cdcTemptblName + ' FROM ' + @cdctblName
EXEC(@sql)
SET @sql = 'ALTER TABLE dbo.'+ @tblName +' ADD '+ @colname + ' '+ @dbType +' NULL '
EXEC(@sql)
SET @sql = 'ALTER TABLE '+ @cdcTemptblName +' ADD '+ @colname + ' '+ @dbType +' NULL '
EXEC(@sql)
exec sys.sp_cdc_disable_table
@source_schema='dbo',
@source_name= @tblName,
@capture_instance= @cdcInst
WAITFOR DELAY '00:00:10'
EXEC sys.sp_cdc_enable_table
@source_schema = 'dbo',
@source_name = @tblName,
@role_name = NULL,
@capture_instance = @cdcInst,
@filegroup_name = 'CDC_TestAudit',
@supports_net_changes = 1
WAITFOR DELAY '00:00:10'
SET @sql = 'INSERT INTO ' + @cdctblName + ' SELECT * FROM ' + @cdcTemptblName
EXEC(@sql)
SET @sql = 'UPDATE cdc.change_tables
SET start_lsn = (SELECT MIN(__$start_lsn) FROM ' +@cdcTemptblName + ')
WHERE capture_instance = ''' + @cdcInst+'''';
EXEC (@sql)
SET @sql = 'DROP TABLE ' + @cdcTemptblName
EXEC (@sql)