0

すでに追跡されているテーブルのCDCにいくつかの列を追加する必要があります。私のアプローチは次のとおりです。

EXEC sys.sp_cdc_drop_job 'capture'

BEGIN TRANSACTION

BEGIN TRY
    -- Copy existing data of the tracked table into a temporary table
    SELECT * INTO CDC.dbo_MyTable_Temp FROM CDC.dbo_MyTable_CT

    -- Add the new column to the temp table. This allows us to just use INSERT..SELECT * later
    ALTER TABLE CDC.dbo_MyTable_Temp ADD MyColumn INT NULL

    -- Disable CDC for the source table temporarily. This will drop the CDC table
    EXEC sys.sp_cdc_disable_table @source_schema = 'dbo', @source_name = 'MyTable', @capture_instance = 'dbo_MyTable'

    -- Reenable CDC for the source table. This will recreate the table with the new columns
    EXEC sys.sp_cdc_enable_table @source_schema = 'dbo', @source_name = 'MyTable', @capture_instance = 'dbo_MyTable', @supports_net_changes = 1, @role_name = NULL, @filegroup_name = 'CDCGROUP'

    -- Insert the old values into the CDC table
    INSERT INTO cdc.dbo_MyTable_CT SELECT * FROM cdc.dbo_MyTable_Temp

    -- Correct the start_lsn in CDC.change_tables. Otherwise all of the CDC stored procedures will be confused
    -- and although the old data will exist in the table the functions won't return it
    UPDATE cdc.change_tables SET start_lsn = (SELECT MIN(__$start_lsn) FROM cdc.dbo_MyTable_Temp) WHERE capture_instance = 'dbo_MyTable'

    -- Drop the temp table
    DROP TABLE cdc.dbo_MyTable_Temp

    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION
    RAISERROR('Error!', 16, 1)
END CATCH

EXEC sys.sp_cdc_add_job 'capture'

ただし、再追加後にジョブを再度実行すると、の主キー制約に違反しているというエラーが生成されCDC.lsn_time_mappingます。

助言がありますか?

ありがとう!

4

1 に答える 1

0

lsn_time_mapping拡張ストアドプロシージャで更新が行われるため、エラーの正確な原因を特定できませんでしたが、別のコードを使用して列を追加することができました。基本的に、私ALTER TABLEはCDCテーブルでコマンドを実行する代わりに、CDCストアドプロシージャに固執しました。コードは以下のとおりです。

-- Create a new capture instance for the table
EXEC sys.sp_cdc_enable_table @source_schema = 'dbo', @source_name = 'MyTable', @capture_instance = 'dbo_MyTable_New', @supports_net_changes = 1, @role_name = NULL, @filegroup_name = 'CDCGROUP'

-- Copy all of the existing data from the old capture instance
INSERT INTO CDC.dbo_MyTable_New_CT SELECT *, NULL AS NewColumn1, NULL AS NewColumn2 FROM CDC.dbo_MyTable_CT

-- Disable the old capture instance
EXEC sys.sp_cdc_disable_table @source_schema = 'dbo', @source_name = 'MyTable', @capture_instance = 'dbo_MyTable'

-- Now we need to jump through some hoops to rename the capture instance back to what it was:
-- Recreate a new capture instance with the old name again
EXEC sys.sp_cdc_enable_table @source_schema = 'dbo', @source_name = 'MyTable', @capture_instance = 'dbo_MyTable', @supports_net_changes = 1, @role_name = NULL, @filegroup_name = 'CDCGROUP'

-- Copy all of the data over again
INSERT INTO CDC.dbo_MyTable_CT SELECT * FROM CDC.dbo_MyTable_New_CT

-- Remove the capture instance that we had been using to add the new columns
EXEC sys.sp_cdc_disable_table @source_schema = 'dbo', @source_name = 'MyTable', @capture_instance = 'dbo_MyTable_New'

-- We need to correct the start_lsn in the cdc.change_tables table. Otherwise all of the CDC stored procedures and views will be confused and
-- although the old data will exist in the CDC table it wouldn't be returned by those CDC procs
UPDATE cdc.change_tables SET start_lsn = (SELECT MIN(__$start_lsn) FROM cdc.dbo_MyTable_CT) WHERE capture_instance = 'dbo_MyTable'

データベースのダウンタイム中にこれを実行していることに注意してください。データベースの使用中にこれを行う必要がある場合はWHERE、同じレコードを1つのテーブルから既に存在するテーブルにコピーしないように、挿入ステートメントに句を追加する必要がある場合があります。両方のキャプチャインスタンスがアクティブな場合、テーブルに影響を与えるDMLは、両方のキャプチャインスタンスに行を配置します。

于 2012-10-31T19:00:07.913 に答える