微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

CDC 在执行存储过程以将新列添加到源表后未捕获更改

如何解决CDC 在执行存储过程以将新列添加到源表后未捕获更改

我找到了这个存储过程并尝试了它。它应该在启用 CDC 时向源表添加/删除列并且不会丢失任何数据。但是在此过程之后,cdc 不再捕获更改。有任何想法吗?可能是什么问题?

使用 [数据库名称]

开始

/*-------------------------------------------- -------------------------------------------------- --------- 如何执行:EXEC usp_AddOrDropColumnToCDCTableWithoutLosingData @SchemaName,@TableName,@ColumnName,@Action

添加新列 示例:EXEC usp_AddOrDropColumnToCDCTableWithoutLosingData 'dbo','T','NAME','ADD'

删除现有列 示例:EXEC usp_AddOrDropColumnToCDCTableWithoutLosingData 'dbo','Name','DROP'

----------------------------------------------- -------------------------------------------------- -------*/ 设置 ANSI_NULLS 开启

开始

设置 QUOTED_IDENTIFIER 开启

开始

创建程序 dbo.Usp_addordropcolumntocdctablewithoutlosingdata @pSchemaName VARCHAR(50),@pTableName VARCHAR(100),@pColumnName VARCHAR(100),@pAction VARCHAR(10) 作为 开始 声明 @vsqlTempTable NVARCHAR(MAX) 声明 @vsqlAlterTable NVARCHAR(MAX) 声明 @vdisableCDC NVARCHAR(MAX) 声明 @vGetAlreadyExistingColumns NVARCHAR(MAX) 声明 @vEnableCDC NVARCHAR(MAX) 声明 @vLoadCDCTable NVARCHAR(MAX) 声明 @vDropCreateTemp NVARCHAR(MAX) 声明 @vDataType VARCHAR(50) 声明 @vColumnList NVARCHAR(2000) 声明 @vColumnExists INT 声明 @vColumnExistsCDC INT 声明 @vTempTableName VARCHAR(100) 声明 @vDropColumnList NVARCHAR(2000) 声明@vDropColumnListExcSys NVARCHAR(2000)

  SET @vTempTableName='##' + @pSchemaName + '_' + @pTableName

  BEGIN TRY
      IF ( @pAction = 'ADD'
            OR @pAction = 'Drop' )
        BEGIN
            --Check if Column exists for SourceTable table
            SET @vColumnExists=(SELECT Count(*)
                                FROM   informatION_SCHEMA.COLUMNS
                                WHERE  TABLE_SCHEMA = @pSchemaName
                                       AND TABLE_NAME = @pTableName
                                       AND COLUMN_NAME = @pColumnName)

            IF ( @vColumnExists = 0
                 AND @pAction = 'ADD' )
              BEGIN
                  PRINT ' COLUMN ::' + @pColumnName
                        + ' does not exists for Source Table ::'
                        + @pTableName
                        + ' Please add column to Source Table to include in CDC Table.'
              END
            ELSE
              BEGIN
                  PRINT ' COLUMN ::' + @pColumnName
                        + ' exists for Source Table ::' + @pTableName
                        + '-->Proceeding to Next Step.'
              END

            --Check if Column exists for CDC table
            IF ( @vColumnExists != 0
                 AND @pAction = 'ADD' )
              SET @vColumnExistsCDC=(SELECT Count(*)
                                     FROM   informatION_SCHEMA.COLUMNS
                                     WHERE  TABLE_SCHEMA = 'cdc'
                                            AND TABLE_NAME = @pSchemaName + '_' + @pTableName + '_CT'
                                            AND COLUMN_NAME = @pColumnName)

            IF ( @vColumnExistsCDC != 0
                 AND @pAction = 'ADD' )
              BEGIN
                  PRINT ' COLUMN ::' + @pColumnName
                        + ' is already part of CDC Tble ::cdc.'
                        + @pSchemaName + '_' + @pTableName + 'CT'
              END

            IF ( @vColumnExistsCDC = 0
                 AND @pAction = 'ADD' )
              BEGIN
                  PRINT ' COLUMN ::' + @pColumnName
                        + ' is not part of CDC Tble ::cdc.'
                        + @pSchemaName + '_' + @pTableName
                        + 'CT -->Proceeding to ADD this column'
              END

            --copY EXISTING CDC TABLE TO TEMP TABLE
            --Drop Temp table before Creating/Loading IT
            SET @vDropCreateTemp=' IF Object_id(N''tempdb..'
                                 + @vTempTableName
                                 + ''') IS NOT NULL
                BEGIN
                    DROP TABLE ##'
                                 + @pSchemaName + '_' + @pTableName + ' END'

            PRINT @vDropCreateTemp

            EXEC (@vDropCreateTemp)

            SET @vsqlTempTable= 'SELECT * INTO ' + @vTempTableName
                                + ' From cdc.' + @pSchemaName + '_' + @pTableName
                                + '_CT'

            PRINT @vsqlTempTable

            EXEC(@vsqlTempTable)

            IF ( @vColumnExistsCDC = 0
                 AND @pAction = 'ADD' )
              BEGIN
                  --ADD COLUMN TO TEMP TABLE
                  SET @vDataType=(SELECT CASE
                                           WHEN DATA_TYPE IN ( 'CHAR','varchar','nvarchar' ) THEN DATA_TYPE + '('
                                                                                                    + Cast(CHaraCTER_MAXIMUM_LENGTH AS VARCHAR(50))
                                                                                                    + ')'
                                           WHEN Data_Type IN ( 'int','bigint','smallint','tinyint','money','bit','date','datetime' ) THEN Data_Type
                                           WHEN data_type IN ( 'numeric','decimal' ) THEN DATA_TYPE + '('
                                                                                           + Cast(Numeric_Precision_Radix AS VARCHAR(50))
                                                                                           + ',' + Cast(Numeric_scale AS VARCHAR(50))
                                                                                           + ')'
                                         END AS DataType
                                  FROM   informatION_SCHEMA.COLUMNS
                                  WHERE  TABLE_NAME = @pTableName
                                         AND COLUMN_NAME = @pColumnName)
                  SET @vsqlAlterTable='ALTER TABLE ' + @vTempTableName + ' ADD '
                                      + @pColumnName + ' ' + @vDataType

                  PRINT @vsqlAlterTable

                  EXEC (@vsqlAlterTable)

                  -- ENABLE CDC ON TABLE ( INCLUDING NEW COLUMN)
                  IF Object_id(N'tempdb..##ColumnList') IS NOT NULL
                    BEGIN
                        DROP TABLE ##ColumnList
                    END

                  CREATE TABLE ##ColumnList
                    (
                       ColumnList NVARCHAR(2000)
                    )

                  SET @vGetAlreadyExistingColumns= N' DECLARE @vCDCAlreadyEnabledColumns NVARCHAR(2000)
                      SELECT @vCDCAlreadyEnabledColumns = COALESCE(@vCDCAlreadyEnabledColumns+ '','','''')
                      + QUOTENAME(COLUMN_NAME) FROM  informatION_SCHEMA.COLUMNS WHERE TABLE_NAME='''
                                                   + @pSchemaName + '_' + @pTableName + '_'
                                                   + 'CT'' AND COLUMN_NAME NOT
                                               IN (''__$start_lsn'',''__$end_lsn'',''__$seqval'',''__$operation'',''__$update_mask'')
                                               PRINT @vCDCAlreadyEnabledColumns
                                               Insert into ##ColumnList values (@vCDCAlreadyEnabledColumns)'

                  PRINT @vGetAlreadyExistingColumns

                  EXEC ( @vGetAlreadyExistingColumns)

                  SELECT @vColumnList = ColumnList + ',[' + @pColumnName + ']'
                  FROM   ##ColumnList

                  PRINT @vColumnList

                  -- disABLE CDC ON SOURCE TABLE
                  SET @vdisableCDC='EXEC sys.sp_cdc_disable_table @source_schema='''
                                   + @pSchemaName + ''',@source_name='''
                                   + @pTableName + ''',@capture_instance='''
                                   + @pSchemaName + '_' + @pTableName + ''''

                  PRINT @vdisableCDC

                  EXEC (@vdisableCDC)

                  --Enable CDC
                  SET @vEnableCDC='EXEC sys.sp_cdc_enable_table
     @source_schema=''' + @pSchemaName
                                  + ''',@source_name=''' + @pTableName
                                  + ''',@role_name=NULL,@captured_column_list= '''
                                  + @vColumnList + ''''

                  PRINT @vEnableCDC

                  EXEC (@vEnableCDC)

                  -- INSERT RECORD FROM Temp to CDC Table
                  SET @vLoadCDCTable=' INSERT INTO cdc.' + @pSchemaName + '_'
                                     + @pTableName
                                     + '_CT
                                  SELECT * FROM '
                                     + @vTempTableName + ''

                  --  Drop Table '+@vTempTableName+''
                  PRINT @vLoadCDCTable

                  EXEC (@vLoadCDCTable)
              END

        /***-------------------------------------DROP COLUMN LOGIC STARTS-----------------------------************/
            --Build Column List excluding Drop column
            IF EXISTS (SELECT 1
                       FROM   informatION_SCHEMA.COLUMNS
                       WHERE  TABLE_SCHEMA = 'cdc'
                              AND TABLE_NAME = @pSchemaName + '_' + @pTableName + '_CT'
                              AND COLUMN_NAME = @pColumnName)
               AND @pAction = 'Drop'
              BEGIN
                  SELECT @vDropColumnList = Stuff(o.COLUMNNAME,1,'')
                  FROM   informatION_SCHEMA.COLUMNS t
                         CROSS APPLY (SELECT ',' + Column_Name + Char(10) AS [text()]
                                      FROM   informatION_SCHEMA.COLUMNS c
                                      WHERE  c.Table_Name = t.Table_Name
                                             AND c.COLUMN_NAME <> @pColumnName
                                      FOR XML PATH('')) o (COLUMNNAME)
                  WHERE  t.Table_Name = 'dbo_' + @pTableName + '_CT'

                  --Get Columns without Sytem Columns 
                  SELECT @vDropColumnListExcSys = Stuff(o.COLUMNNAME,' + Column_Name + Char(10) AS [text()]
                                      FROM   informatION_SCHEMA.COLUMNS c
                                      WHERE  c.Table_Name = t.Table_Name
                                             AND c.COLUMN_NAME <> @pColumnName
                                             AND C.COLUMN_NAME NOT IN ( '__$start_lsn','__$end_lsn','__$seqval','__$operation','__$update_mask' )
                                      FOR XML PATH('')) o (COLUMNNAME)
                  WHERE  t.Table_Name = 'dbo_' + @pTableName + '_CT'

                  -- disABLE CDC for Drop Column
                  SET @vdisableCDC='EXEC sys.sp_cdc_disable_table @source_schema='''
                                   + @pSchemaName + ''',@capture_instance='''
                                   + @pSchemaName + '_' + @pTableName + ''''

                  EXEC (@vdisableCDC)

                  -- ENABLE TABLE EXCLUDING GIVEN COLUMN
                  SET @vEnableCDC='EXEC sys.sp_cdc_enable_table
     @source_schema=''' + @pSchemaName
                                  + ''',@captured_column_list= '''
                                  + @vDropColumnListExcSys + ''''

                  EXEC (@vEnableCDC)

                  --copY DATA FROM TEMP DATA TO CDC TABLE
                  SET @vLoadCDCTable=' INSERT INTO cdc.' + @pSchemaName + '_'
                                     + @pTableName + '_CT(' + @vDropColumnList
                                     + ')
                                  SELECT '
                                     + @vDropColumnList + ' FROM ' + @vTempTableName
                                     + ''

                  --Drop Table '+@vTempTableName+''
                  EXEC (@vLoadCDCTable)
              END
        END
      ELSE
        PRINT ' ADD OR Drop are the correct actions available for this Procedure.Please provide ADD or Drop for SP Signature'
  END TRY

  BEGIN CATCH
      ROLLBACK

      PRINT ' ERROR Occured and All Transactions are rolledback.'
  END CATCH

结束

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。