SQL SERVER 2008 数据变更捕获(CDC )

原文转载:http://blog.csdn.net/ldslove/archive/2010/05/20/5612248.aspx

SQL SERVER 2008 异步捕获表数据修改

 

写的不对的地方请各位指正,写的也比较乱。讲究这看吧。^ ^

/*

SQL SERVER 2008 异步捕获表数据修改

 

 

SQL server 2008为异步跟踪所有发生在用户表上的数据修改提供了内建的方法,

而不需要编写自定义的触发器或者查询,变更数据捕获拥有最小性能开销,可以

用于其它数据源的持续更新,例如,将OLTP数据库中的数据变更迁移到数据仓库

数据库.下面我们演示该功能.

 

 

*/

 

 

/*

  1 建立测试数据库

*/

IF NOT EXISTS (SELECT NAME FROM SYS.databases WHERE name='CDC_TEST_DB')

 

BEGIN

    CREATE DATABASE CDC_TEST_DB

END

 

/*

  2 在把CDC增加到CDC_TEST_DB数据库的表中,首先应该验证数据库是否启用了数据

    捕获

*/

 

    --验证是否开启

    SELECT IS_CDC_ENABLED FROM SYS.databases WHERE name='CDC_TEST_DB'

    /*

    IS_CDC_ENABLED

    --------------

    0

 

    (1 行受影响)

    */

 

    --启用数据变更,在CDC_TEST_DB数据库中执行SYS.SP_CDC_ENABLE_DB存储过程:

 

    USE CDC_TEST_DB

    GO

 

    EXEC sys.SP_CDC_ENABLE_DB

    GO

 

    /*

      CDC_TEST_DB开启数据捕获后,你将会在CDC_TEST_DB->安全性->架构下面看到新

      建立了一个CDC架构.

 

      同样在CDC_TEST_DB会建立一些CDC架构的下的系统表:

       cdc.captured_columns

       返回指定的跟踪列

 

       cdc.change_tables

       返回启用CDC的表.使用sys.sp_cdc_help_change_data_capture比直接查询好.

 

       cdc.ddl_history

       返回每个表再启用CDC后的DDL变更.可以使用sys.sp_cdc_get_ddl_history代替查询该表.

 

       cdc.index_columns

       返回启用CDC的表的相关索引列.同样用sys.sp_cdc_help_change_data_capure来获取比较好.

 

       cdc.lsn_time_mapping

       为每个在更改表中存在行的事务返回一行.该表用于在日志序列号(LSN) 提交值和提交事务的时间之间建立映射.

       要避免直接查询该表,使用sys.fn_cdc_map_lsn_to_time和sys.fn_cdc_map_time_to_lsn函数.

 

    */

 

    --下面再验证看看是否已经开启数据库开启

    SELECT IS_CDC_ENABLED FROM SYS.databases WHERE name='CDC_TEST_DB'

 

    /*

    IS_CDC_ENABLED

    --------------

    1

 

    (1 行受影响)

    */

 

/*

  3 开启数据捕获之后,可以在数据库中通过使用SYS.SP_CDC_ENABLE_TABLE系统SP对表进行

     变更捕获.SP描述如下

       sys.sp_cdc_enable_table

       [ @source_schema = ] 'source_schema',

       [ @source_name = ] 'source_name' ,

       [ @role_name = ] 'role_name'

       [,[ @capture_instance = ] 'capture_instance' ]

       [,[ @supports_net_changes = ] supports_net_changes ]

       [,[ @index_name = ] 'index_name' ]

       [,[ @captured_column_list = ] 'captured_column_list' ]

       [,[ @filegroup_name = ] 'filegroup_name' ]

       [,[ @allow_partition_switch = ] 'partition_switch' ]

 

    @source_schema :

    是源表所属的架构的名称.source_schema 的数据类型为sysname,无默认值,并且

    不能为NULL.

 

    @source_name :

    是对其启用变更数据捕获的源表的名称.source_name 的数据类型为sysname,无默

    认值,并且不能为NULL.   source_name 必须存在于当前数据库中.不能对cdc 架构

    中的表启用变更数据捕获.

 

    @role_name :

    是用于控制更改数据访问的数据库角色的名称.role_name 为sysname,并且必须指定.

    如果显式设置为NULL,则没有控制角色用于限制对更改数据的访问.如果当前存在该角

    色,则使用它.如果不存在该角色,则会尝试创建具有指定名称的数据库角色.在尝试创

    建该角色之前,将删除角色名称字符串右侧的空格.如果调用方无权在数据库中创建角色,

    则存储过程操作将失败.

 

    @capture_instance :

    是用于命名特定于实例的变更数据捕获对象的捕获实例的名称.capture_instance 为

    sysname,并且不能为NULL.源表最多可以有两个捕获实例.

 

    @supports_net_changes :

    指示是否对此捕获实例启用净更改查询支持.supports_net_changes 为bit,如果此表有

    主键,或者有已使用@index_name 参数进行标识的唯一索引,则此参数的默认值为1.否

    则,此参数默认为0.如果为0,则只生成查询所有更改的支持函数.如果为1,则还会生

    成查询净更改所需的函数.

 

    如果将supports_net_changes 设置为1,则必须指定index_name,或者源表必须具有已

    定义的主键.

 

    @index_name :

    用于唯一标识源表中的行的唯一索引的名称.index_name 为sysname,并且可以为NULL.如

    果指定,则index_name 必须是源表的唯一有效索引.如果指定index_name,则标识的索引列

    优先于任何定义的主键列,就像表的唯一行标识符一样. 

 

    @captured_column_list :

    标识将包括在更改表中的源表列.captured_column_list 的数据类型为nvarchar(max),并且

    可以为NULL.如果为NULL,则所有列都将包括在更改表中.

 

    @filegroup_name : 这个选项允许指定CDC的数据存储到哪里.filegroup_name 为sysname,并且

    可以NULL.如果指定   ,则必须为当前数据库定义filegroup_name.如果为NULL,则使用默认文

    件组.   对于大型数据集,通过不同的文件组进行分隔会带来更好的管理型和性能.

 

    @allow_partition_switch : 指示是否可以对启用了变更数据捕获的表执行ALTER TABLE 的SWITCH

    PARTITION 命令.allow_partition_switch 为bit,默认值为1.

 

 

*/

 

 

    --创建测试表

 

    CREATE TABLE TB_CDC_USER(

       USERID  INT NOT NULL PRIMARY KEY  IDENTITY(1,1)

       ,NAME VARCHAR(20) NOT NULL

       ,ADDRESS  VARCHAR(100) NOT NULL)

 

 

    INSERT TB_CDC_USER(NAME,ADDRESS) VALUES

    ('香蕉','dss省fdfd市'),

    ('鸽子','山东省青岛市'),

    ('水哥','江苏省苏州市'),

    ('土豆','XX省XX市');

 

 

    --捕获所有行发生的变更,只返回行的净变更.其它为默认值

 

    EXEC sys.sp_cdc_enable_table

       @source_schema ='dbo'

       ,@source_name='TB_CDC_USER'

       ,@role_name=null

       ,@capture_instance=null

       ,@supports_net_changes=1

       ,@index_name=null

       ,@captured_column_list=null

       ,@filegroup_name=default

       ,@allow_partition_switch=1

/*    

    执行后会启动个作业,每个启用表CDC的都会启用以下个作业.

    如果已经存在启用了CDC的表,则作业不会被重建

 

       cdc.CDC_TEST_DB_capture  捕获作业

           该作业的职责是使用日志读取器技术捕获发生的变更,并且在

           SQLSERVER启动并运行时设定为自动运行.当JOB运行的时候会

           调用系统SP sys.sp_MScdc_capture_job,该sp内部调用调用

           sys.sp_cdc_scan.如果变更数据捕获日志扫描操作已经处于

           活动状态,或数据库启用了事务复制,则无法显式执行此过程.

           此存储过程应当由需要自定义自动配置的捕获作业的行为的管

           理员使用.

 

 

       cdc.CDC_TEST_DB_cleanup  清除作业

           默认为每天上午点运行,默认是清除存放天以上的数据.

           调用系统存储过程sys.sp_MScdc_cleanup_job

 

 

    执行成功之后同样在CDC_TEST_DB数据库系统表中会生成表cdc.dbo_TB_CDC_USER_CT,

    该表包含TB_CDC_USER_CT表上所有的变更.展开表后会发现新增加了列.

       __$start_lsn  与相应更改的提交事务关联的日志序列号(LSN).

       __$end_lsn

        __$seqval     用于对事务内的行更改进行排序的序列值.

       __$operation 识与相应更改关联的数据操作语言(DML) 操作.可以是下列值之一:

                     1 = 删除;2 = 插入;3 = 更新(旧值)列数据中具有执行更新语句之

                     前的行值.4 = 更新(新值)列数据中具有执行更新语句之后的行值.

 

 

       __$update_mask    基于更改表的列序号的位掩码,用于标识那些发生更改的列。

 

    其中很重要的列__$operation and __$update_mask

 

*/

 

 

/*

    通过下面的查询确认这个表已经被跟踪

*/ 

    SELECT is_tracked_by_cdc

    FROM SYS.TABLES

    WHERE NAME='TB_CDC_USER'

         AND SCHEMA_ID=SCHEMA_ID('DBO')

/*   

    is_tracked_by_cdc

    -----------------

    1

 

    (1 行受影响)

*/

 

 

/*

    也可以使用sys.sp_cdc_help_change_data_capture来验证数据捕获的配置.

       sys.sp_cdc_help_change_data_capture

         [ [ @source_schema = ] 'source_schema' ]--表的架构名

         [, [ @source_name = ] 'source_name' ]      --表名称

*/

 

    EXEC sys.sp_cdc_help_change_data_capture 'DBO','TB_CDC_USER'

/* 

    查询结果:

    source_schema            dbo

    source_table             TB_CDC_USER

    capture_instance         dbo_TB_CDC_USER

    object_id                373576369

    source_object_id start_lsn  309576141

    end_lsn                     0x0000001A000001CE003B

    supports_net_changes     NULL

    has_drop_pending         1

    role_name                NULL

    index_name               NULL

    filegroup_name              PK__TB_CDC_U__7B9E7F35145C0A3F

    create_date                 2010-05-20 11:48:58.177

    index_column_list        [USERID]

    captured_column_list     [USERID], [NAME], [ADDRESS]

*/

 

 

 

/*

  4 进行变更捕获测试.

 

     先查看那表中都写什么数据.

*/

 

       USE CDC_TEST_DB

       GO

       SELECT *

       FROM dbo.TB_CDC_USER

       GO

 

       SELECT *

       FROM cdc.dbo_TB_CDC_USER_CT

       GO

 

       /*结果

       USERID      NAME                 ADDRESS

       ----------- -------------------- ------------------

       1           香蕉                  dss省fdfd市

       2           鸽子                  山东省青岛市

       3           水哥                  江苏省苏州市

       4           土豆                  XX省XX市

 

       (4 行受影响)

 

       __$start_lsn  __$end_lsn   __$seqval __$operation __$update_mask USERID  NAME  ADDRESS

       ------------- -----------  --------- ------------ -------------- ------- ----- --------

 

       (0 行受影响)

       */

 

 

    --  4.1 插入操作

 

    USE CDC_TEST_DB

    GO

 

    INSERT TB_CDC_USER(NAME,ADDRESS) VALUES

    ('九零后','毛毛省毛毛市')

 

 

    SELECT *

    FROM dbo.TB_CDC_USER

    GO

 

    SELECT *

    FROM cdc.dbo_TB_CDC_USER_CT

    GO

    /*

    USERID      NAME                 ADDRESS

    ----------- -------------------- ---------------------

    1           香蕉                  dss省fdfd市

    2           鸽子                  山东省青岛市

    3           水哥                  江苏省苏州市

    4           土豆                  XX省XX市

    5           九零后                 毛毛省毛毛市

 

    (5 行受影响)

 

    __$start_lsn         __$end_lsn __$seqval            __$operation  __$update_mask    USERID  NAME   ADDRESS

    ----------------------   ----------- --------------------- ------------  --------------    ------- ------    ------------

    0x0000002C000001E30004   NULL       0x0000002C000001E30003   2             0x07          5       九零后  毛毛省毛毛市

 

    (1 行受影响)

 

    上面的结果中看出当TB_CDC_USER插入一条数据后,同样在跟踪表中可以有一条相同的数据_operation

    值为代表这是一条插入操作.

    */

 

 

    --4.2更新操作

 

    USE CDC_TEST_DB

    GO

 

    UPDATE TB_CDC_USER

    SET ADDRESS='YY省YY市'

    WHERE USERID=5

 

    SELECT *

    FROM dbo.TB_CDC_USER

    GO

 

    SELECT *

    FROM cdc.dbo_TB_CDC_USER_CT

    GO

 

    /*结果

    USERID      NAME                 ADDRESS

    ----------- -------------------- ---------------

    1           香蕉                  dss省fdfd市

    2           鸽子                  山东省青岛市

    3           水哥                  江苏省苏州市

    4           土豆                  XX省XX市

    5           九零后                 YY省YY市

 

    (5 行受影响)

 

    __$start_lsn         __$end_lsn __$seqval            __$operation  __$update_mask    USERID  NAME   ADDRESS

    ----------------------   ----------- --------------------- ------------  --------------    ------- ------    ------------

    0x0000002C000001E30004   NULL       0x0000002C000001E30003   2             0x07          5       九零后  毛毛省毛毛市

    0x0000002D0000004D0004   NULL       0x0000002D0000004D0002   3             0x04          5       九零后  毛毛省毛毛市

    0x0000002D0000004D0004   NULL       0x0000002D0000004D0002   4             0x04          5       九零后  YY省YY市

 

 

    同样我们查询dbo_TB_CDC_USER_CT后会发现比之前多了条数据,分别为USERID=6这条数据更新

    前和更新后的数据,__$operation为代表UPDATE前的数据,4为UPDATE后的数据.如果是多列数据

    一起更新同样是跟新前和更新后各对应一条捕获数据.

    */

 

 

    --4.3 删除操作

 

 

    USE CDC_TEST_DB

    GO

 

    DELETE FROM  TB_CDC_USER WHERE USERID=5

 

    SELECT *

    FROM dbo.TB_CDC_USER

    GO

 

    SELECT *

    FROM cdc.dbo_TB_CDC_USER_CT

    GO

 

    /*结果

    USERID      NAME                 ADDRESS

    ----------- -------------------- ------------------

    1           香蕉                  dss省fdfd市

    2           鸽子                  山东省青岛市

    3           水哥                  江苏省苏州市

    4           土豆                  XX省XX市

 

    (4 行受影响)

 

    __$start_lsn         __$end_lsn __$seqval            __$operation  __$update_mask    USERID  NAME   ADDRESS

    ----------------------   ----------- --------------------- ------------  --------------    ------- ------    ------------

    0x0000002C000001E30004   NULL       0x0000002C000001E30003   2             0x07          5       九零后  毛毛省毛毛市

    0x0000002D0000004D0004   NULL       0x0000002D0000004D0002   3             0x04          5       九零后  毛毛省毛毛市

    0x0000002D0000004D0004   NULL       0x0000002D0000004D0002   4             0x04          5       九零后  YY省YY市

    0x00000035000001310005   NULL       0x00000035000001310002   1             0x07          5       九零后  YY省YY市

 

    和跟新后的dbo_TB_CDC_USER_CT表相比多了一条__$operation=1 的数据,代表了删除操作所捕获的数据.

    */

 

/*

  5 查询变更数据

*/

 

    /*生成变更后就可以用CDC函数查看变更历史了,使用日志序列号(Log sequence number,LSN)

      跟踪数据的变更.LSN是在事务日志中唯一标志一个活动记录.

 

 

      使用函数sys.fn_cdc_map_time_to_lsn获取变更范围内的的最大和最小LSN值.这函数有个

      输入值关系运算符和跟踪时间(还可以用其他的方法确定LSN,下面会讲到).关系运算符有:

      smallest greater than;  smallest greater than or equal;    largest less than;

      largest less than or equal.

 

    */

    --获得对应时间内的LSN边界.

    SELECT SYS.fn_cdc_map_time_to_lsn('smallest greater than or equal','2010-05-20 14:00:00') AS BGLSN

    SELECT SYS.fn_cdc_map_time_to_lsn('largest less than or equal','2010-05-20 16:00:00') AS EDLSN

 

    /*

    根据LSN边界用函数CDC.fn_cdc_get_all_changes_dbo_TB_CDC_USER获得时间段内的净变更.

    MSDN:cdc.fn_cdc_get_all_changes_<捕获实例> http://msdn.microsoft.com/zh-cn/vstudio/bb510627.aspx

 

    为了防止出现指定的LSN 范围不在捕获实例的更改跟踪时间线范围之内,则函数将返回错误208(“为过程或函数

    cdc.fn_cdc_get_all_changes 提供的参数数目不足。”)。各位在测试的时候可以先通过

    sys.fn_cdc_map_lsn_to_time函数来查询一下变更的时间.

 

    我在这地方郁闷了老半天

    */

 

    SELECT __$OPERATION,sys.fn_cdc_map_lsn_to_time(__$start_lsn),USERID,NAME,ADDRESS

    FROM cdc.dbo_TB_CDC_USER_CT

 

    /*

    __$OPERATION                         USERID      NAME                 ADDRESS

    ------------ ----------------------- ----------- -------------------- ----------------

    2            2010-05-20 15:43:24.920 5           九零后                 毛毛省毛毛市

    3            2010-05-20 15:49:54.203 5           九零后                 毛毛省毛毛市

    4            2010-05-20 15:49:54.203 5           九零后                 YY省YY市

    1            2010-05-20 16:16:17.280 5           九零后                 YY省YY市

 

    (4 行受影响)

    */

 

    DECLARE @BGLSN VARBINARY(10)=SYS.fn_cdc_map_time_to_lsn('smallest greater than or equal','2010-05-20 15:43:24.920')--该处的时间如果早于你CDC开启的时间会出问题

    DECLARE @EDLSN VARBINARY(10)=SYS.fn_cdc_map_time_to_lsn('largest less than or equal','2010-05-21 16:16:17.280')

    SELECT __$OPERATION

           ,__$UPDATE_MASK

           ,USERID

           ,NAME

           ,ADDRESS

    FROM   cdc.fn_cdc_get_all_changes_dbo_TB_CDC_USER(@BGLSN,@EDLSN,'all')  --all | all update old

 

    /*结果

    __$OPERATION __$UPDATE_MASK USERID      NAME                 ADDRESS

    ------------ -------------- ----------- -------------------- ------------

    2            0x07           5           九零后              毛毛省毛毛市 --为插入的数据

    4            0x04           5           九零后              YY省YY市      --数据行更新后的版本

    1            0x07           5           九零后              YY省YY市      --为删除的数据

 

    (3 行受影响)

 

    以上结果展示了该表发生的所有更改.大家应该能够理解cdc.fn_cdc_get_all_changes_dbo_TB_CDC_USER是根

    据你的原表进行命名的.同时查询的数据源表cdc.dbo_TB_CDC_USER_CT中的数据相比少了一条__$OPERATION为

    3的那行数据,那是因为参数ALL影响的.下面会有ALL UPDATE OLD选项的查询.

 

 

    也许下面的查询结果更好理解一点

    */

 

    DECLARE @BGLSN VARBINARY(10)=SYS.fn_cdc_map_time_to_lsn('smallest greater than or equal','2010-05-20 15:43:24.920')

    DECLARE @EDLSN VARBINARY(10)=SYS.fn_cdc_map_time_to_lsn('largest less than or equal','2010-05-20 16:16:17.280')

 

    SELECT CASE __$OPERATION

                WHEN 1 THEN '删除的数据'

                WHEN 2 THEN '插入的数据'

                WHEN 3 THEN '更新前的数据行'

                WHEN 4 THEN '更新后的数据行'

            END AS OPERATION

           ,__$UPDATE_MASK

           ,USERID

           ,NAME

           ,ADDRESS

    FROM   cdc.fn_cdc_get_all_changes_dbo_TB_CDC_USER(@BGLSN,@EDLSN,'all update old')

 

    /*结果

    OPERATION         __$UPDATE_MASK   USERID      NAME  ADDRESS

    --------------       ---------------- ----------- ------- -------------

    插入的数据         0x07         5           九零后   毛毛省毛毛市

    更新前的数据行     0x04         5           九零后   毛毛省毛毛市

    更新后的数据行     0x04         5           九零后   YY省YY市

    删除的数据         0x07         5           九零后   YY省YY市

 

    (4 行受影响)

    */

 

    /*

    从CDC表查询净变更.

    在开始开启CDC的时候,执行sp_cdc_enbale_table_change_data_capture时@supports_net_changes=1

    该参数决定我们可以选择CDC净变更版本.用fn_cdc_get_net_changes_dbo_TB_CDC_USER来获得.该函

    数和cdc.fn_cdc_get_all_changes_dbo_TB_CDC_USER相似同样接收个参数.前个参数接收起始LSN

    边界值,第个不同.

       all : 返回行最后的更改,不显示更新掩码的值.

       all with mask :返回行最后的更改和掩码值.

       all with merge :返回行最终的更改,不管是删除还是合并操作(插入或者更新)插入和更新不会

                     被打断.由于用来确定给定更改的精确操作的逻辑会增加查询的复杂性,所以

                     ,在只需指出应用更改数据所需的操作是插入还是更新但不必明确区分这两

                     者时,使用该选项可提高查询性能.

 

 

    为了更清楚一点,下面进行一些数据修改.*/

 

    USE CDC_TEST_DB

    GO

 

    INSERT TB_CDC_USER(NAME,ADDRESS) VALUES

    ('九零后','毛毛省毛毛市')

    --该条记录的USERID应该是

 

    UPDATE TB_CDC_USER

    SET ADDRESS='YY省YY市'

    WHERE USERID=6

 

 

    --查询前后的净更改

 

    /*  此处说明一下下面个函数返回的__$OPERATION

       如果第三个参数的值为all 或all with mask,则此列中的值可以是以下值之一:

       1 = 删除;2 = 插入;4 = 更新

 

       如果第三个参数参数的值为all with merge,则此列中的值可以是以下值之一:

       1 = 删除;5 = 插入或更新

       值为5 表示行是否已存在以及是否只需要更新是未知的,或者行当前是否存在以

       及是否必须插入是未知的。

    */

 

    DECLARE @BEGINDATE DATETIME='2010-05-20 18:50:17.280'

    DECLARE @ENDDATE DATETIME='2010-05-20 19:00:00'

 

 

    DECLARE @BGLSN VARBINARY(10)=SYS.fn_cdc_map_time_to_lsn('smallest greater than or equal',@BEGINDATE)

    DECLARE @EDLSN VARBINARY(10)=SYS.fn_cdc_map_time_to_lsn('largest less than or equal',@ENDDATE)

 

    SELECT

           CASE __$OPERATION

              WHEN 1 THEN '删除'

              WHEN 2 THEN '插入'

              WHEN 4 THEN '更新'

              WHEN 5 THEN '合并'

           END AS OPERATION

           ,__$UPDATE_MASK

           ,USERID

           ,NAME

           ,ADDRESS

    FROM   CDC.FN_CDC_GET_NET_CHANGES_DBO_TB_CDC_USER(@BGLSN,@EDLSN,'all with mask')

 

 

    /*

    OPERATION  __$UPDATE_MASK    USERID NAME        ADDRESS

    ---------- ---------------  ------ ----------- -----------

    插入    NULL           6      九零后     YY省YY市

 

    (1 行受影响)

 

    上面的操作我是先插入一条数据,然后更新它,查询对应的LSN范围内净变更,虽然生成次变更

    但是只需要返回一行来反映最终的变更,即最终的INSERT操作

    */

 

 

 

    /*翻译CDC更新掩码

 

      通过上面的个函数cdc.fn_cdc_get_net_changes_..和cdc.fn_cdc_get_net_changes_..返

      回的更新掩码可以确定哪些列被操作影响了.需要借助下面的个CDC函数.

 

      sys.fn_cdc_is_bit_set检查是否在掩码中设定了指定位.它的第一个参数是要检查的位序号

      ,第二个参数是更新掩码本身. 返回值为BIT

 

      将sys.fn_cdc_get_column_ordinal和sys.fn_cdc_is_bit_set一起使用来确定表列的序号位

      置,该函数第一个参数是捕获实例的名称.第二个参数是列的名称.返回值INT型列序号位置.

 

     下面使用者个函数来识别在指定的LSN边界中更新了哪些列.

    */

 

 

 

     USE CDC_TEST_DB

     GO

 

 

     ---SELECT GETDATE() '2010-05-20 19:37:57.910'

     UPDATE TB_CDC_USER

     SET NAME='小草'

     WHERE USERID=1

 

     UPDATE TB_CDC_USER

     SET ADDRESS='火星'

     WHERE USERID=4

 

     --下面使用更新掩码来侦测哪些累发生了改变.

 

     DECLARE @BEGINDATE DATETIME='2010-05-20 19:37:57.910'

     DECLARE @ENDDATE DATETIME='2010-05-20 23:59:59'

 

 

     DECLARE @fromLSN VARBINARY(10)=SYS.fn_cdc_map_time_to_lsn('smallest greater than or equal',@BEGINDATE)

     DECLARE @toLSN VARBINARY(10)=SYS.fn_cdc_map_time_to_lsn('largest less than or equal',@ENDDATE)

 

 

     SELECT

           sys.fn_cdc_is_bit_set(

           --该函数的第一个参数是希望检测的列的序号位置.为了返回序号

           --调用如下函数

                  sys.fn_cdc_get_column_ordinal(

                     'DBO_TB_CDC_USER','NAME')

           --第二个参数是更新掩码本身,调用更更新掩码列.

                     ,__$update_mask) NAME_UPDATED,

           sys.fn_cdc_is_bit_set(

                  sys.fn_cdc_get_column_ordinal(

                     'DBO_TB_CDC_USER','ADDRESS')

                     ,__$update_mask) ADDRESS_UPDATED

           ,USERID

           ,NAME

           ,ADDRESS

     FROM  CDC.FN_CDC_GET_ALL_CHANGES_DBO_TB_CDC_USER(@fromLSN,@toLSN,'all')

     --限定返回类型为的行,它是更新操作之后的行

     WHERE __$OPERATION= 4

 

 

    /*结果

 

    NAME_UPDATED ADDRESS_UPDATED USERID      NAME                 ADDRESS

    ------------ --------------- ----------- -------------------- --------------

    1            0               1           小草                  dss省fdfd市

    0            1               4           土豆                  火星

 

    (2 行受影响)

 

 

    结果中一个更新了NAME,一个更新了ADDRESS.

    */

 

/*

  6 使用LSN边界

 

  可以使用sys.fn_cdn_map_time_to_lsn来确定最大最小LSN边界.以下的几个函数都可以用来产生

  LSN值.

       sys.fn_cdc_incremnet_lsn 返回基于输入的LSN的下一个LSN值.

       sys.fn_cdc_decrement_lsn 看名字可以知道应该是返回输入的LSN之前的LSN值.

       sys.fn_cdc_get_max_lsn 在捕获实例收集的CDC数据中返回最大的LSN.

       sys.fn_cdc_get_min_lsn 在捕获实例收集的CDC数据中返回最小的LSN.

*/    

 

       select sys.fn_cdc_get_max_lsn() as max_lsn --返回数据库级别的最大LSN

       select sys.fn_cdc_get_min_lsn('dbo_tb_cdc_user') as min_lsn--需要捕获实例名称做参数

       select sys.fn_cdc_increment_lsn(sys.fn_cdc_get_max_lsn()) -- 新的下界LSN

       select sys.fn_cdc_decrement_lsn(sys.fn_cdc_get_max_lsn()) -- 新的下界LSN之前的LSN

       /*结果

              max_lsn

       ----------------------

       0x0000003B0000016F0001

 

       (1 行受影响)

 

       min_lsn

       ----------------------

       0x00000029000000A9003F

 

       (1 行受影响)

 

 

       ----------------------

       0x0000003B0000016F0002

 

       (1 行受影响)

 

 

       ----------------------

       0x0000003B0000016F0000

 

       (1 行受影响)

       */

 

/*

  禁用表和数据的变更数据捕获

 

 

         禁用表数据捕获.

         sys.sp_cdc_disable_table

         [ @source_schema = ] 'source_schema' , --架构名称

         [ @source_name = ] 'source_name'       --表名称

         [ , [ @capture_instance = ] 'capture_instance' | 'all' ] --开始启用CDC时写入参数

 

 

         禁用数据CDC,执行如下过程后将从数据库完整删除CDC功能.相关架构和作业一并删除

         sys.sp_cdc_disable_db

 

 

*/        

         exec sys.sp_cdc_disable_table 'dbo','TB_CDC_USER','ALL' ---禁用表变更数据捕获

 

         SELECT IS_TRACKED_BY_CDC FROM SYS.TABLES

         WHERE NAME ='TB_CDC_USER'  AND SCHEMA_ID=SCHEMA_ID('DBO')

 

         /*

           IS_TRACKED_BY_CDC

           -----------------

           0

 

           (1 行受影响)

 

饿的药死

         */

转载于:https://www.cnblogs.com/ylqmf/archive/2010/05/22/1741428.html

你可能感兴趣的:(SQL SERVER 2008 数据变更捕获(CDC ))