<cdc.fn_cdc_get_net_changes_capture_instance> (Transact-SQL)

适用于:SQL Server

为指定的日志序列号 (LSN) 范围内更改的每个源行返回一个净更改行。

等等,什么是 LSN? SQL Server事务日志中的每个记录都由日志序列号 (LSN) 唯一标识。 LSN 排序后,如果 LSN2 大于 LSN1,则 LSN2 引用的日志记录所描述的更改发生在日志记录 LSN 描述的更改 之后

发生重大事件的日志记录的 LSN 可用于构造正确的还原序列。 由于 LSN 是有序的,因此可以比较它们是否相等, (即 <、、 >、= <、= >) 。 构造还原顺序时,这种比较很有用。

如果源行在 LSN 范围内有多个更改,则下面所述的枚举函数将返回反映该行最终内容的单个行。 例如,如果事务在源表中插入一行,而 LSN 范围内的后续事务将更新该行中的一列或多列,则函数仅返回 行,其中包括更新的列值。

此枚举函数是在对某源表启用变更数据捕获并指定净跟踪时创建的。 若要启用净跟踪,源表必须具有主键或唯一索引。 函数名称派生并使用 格式 cdc.fn_cdc_get_net_changes_<capture_instance>,其中 <capture_instance> 是在为更改数据捕获启用源表时为捕获实例指定的值。 有关详细信息,请参阅 sys.sp_cdc_enable_table (Transact-SQL)

Transact-SQL 语法约定

语法

  
cdc.fn_cdc_get_net_changes_capture_instance ( from_lsn , to_lsn , '<row_filter_option>' )  
  
<row_filter_option> ::=  
{ all  
 | all with mask  
 | all with merge  
}  

参数

from_lsn

LSN,它表示要包含在结果集中的 LSN 范围的低端点。 from_lsn二进制 (10)

仅 cdc 中的行 。[capture_instance]_CT 更改表的值在 __$start_lsn 大于或等于 from_lsn 包含在结果集中。

to_lsn

LSN,它表示要包含在结果集中的 LSN 范围的高端点。 to_lsn二进制 (10)

仅 cdc 中的行 。[capture_instance]_CT 更改表的值在 __$start_lsn 小于或等于 from_lsn 或等于 to_lsn 包含在结果集中。

<>row_filter_option ::= { all | all with mask | all with merge }

控制元数据列的内容和结果集中所返回的行的选项。 可以是下列选项之一:

all
返回对元数据列 __$start_lsn 和 __$operation 中的行所做最后更改的 LSN 以及应用这些行所需的操作。 列 __$update_mask 始终为 NULL。

all with mask
返回对元数据列 __$start_lsn 和 __$operation 中的行所做最后更改的 LSN 以及应用这些行所需的操作。 另外,当更新操作返回 (__$operation = 4) 时,更新操作中修改过的已捕获列会在 __$update_mask 中返回的值中进行标记。

all with merge
返回对元数据列 __$start_lsn 中的行所做的最终更改的 LSN。 列 __$operation 为下列两个值之一:1 表示删除,5 表示应用更改所需的操作是插入或更新。 列 __$update_mask 始终为 NULL。

由于用来确定给定更改的精确操作的逻辑会增加查询的复杂性,所以,在只需指出应用更改数据所需的操作是插入还是更新但不必明确区分这两者时,使用该选项可提高查询性能。 此选项在直接提供合并操作的目标环境中最具吸引力。

返回的表

列名称 数据类型 说明
__$start_lsn binary(10) 与更改的提交事务关联的 LSN。

在同一事务中提交的所有更改将共享同一个提交 LSN。 例如,如果源表上的更新操作修改了两行中的两列,则更改表将包含四行,每个行具有相同的 __$start_lsnvalue。
__$operation int 标识将更改数据行应用到目标数据源所需的数据操作语言 (DML) 操作。

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

1 = 删除

2 = 插入

4 = 更新

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

1 = 删除

5 = 插入或更新
__$update_mask varbinary(128) 位掩码,为捕获实例标识的每个已捕获列均对应于一个位。 如果 __$operation = 1 或 2,该值将所有已定义的位设置为 1。 如果 __$operation = 3 或 4,则只有那些对应已更改列的位设置为 1。
<捕获的源表列> 多种多样 函数返回的其余列是在创建捕获实例时源表中标识为已捕获列的那些列。 如果已捕获列的列表中未指定任何列,则将返回源表中的所有列。

权限

要求具有 sysadmin 固定服务器角色或 db_owner 固定数据库角色的成员身份。 对于所有其他用户,要求对源表中的所有已捕获列具有 SELECT 权限;如果已定义捕获实例的访问控制角色,则还要求具有该数据库角色的成员身份。 当调用方没有查看源数据的权限时,该函数将为所有列返回一个具有 NULL 值的行。

备注

修改行的唯一标识符将导致 fn_cdc_get_net_changes 显示初始 UPDATE 命令,并改为使用 DELETE 和 INSERT 命令。 此行为对于在更改之前和之后跟踪密钥是必需的。

如果在调用 cdc.fn_cdc_get_all_changes_<capture_instance>cdc.fn_cdc_get_net_changes_<capture_instance>时提供的 LSN 范围不合适,则预期会出现错误 313。 lsn_value如果参数超过最低 LSN 或最高 LSN 的时间,则执行这些函数将返回错误 313:Msg 313, Level 16, State 3, Line 1 An insufficient number of arguments were supplied for the procedure or function。 此错误应由开发人员处理。 有关解决方法的示例 T-SQL,请参阅 GitHub 上的 ReplTalk

示例

以下示例使用 函数 cdc.fn_cdc_get_net_changes_HR_Department 报告在特定时间间隔内对源表 HumanResources.Department 所做的净更改。

首先,GETDATE 函数用于标记时间间隔的开始。 在将多个 DML 语句应用到源表后,再次调用 GETDATE 函数可标识时间间隔的结束。 然后使用 函数 sys.fn_cdc_map_time_to_lsn 将时间间隔映射到由 LSN 值限制的变更数据捕获查询范围。 最后,查询函数 cdc.fn_cdc_get_net_changes_HR_Department 以获取该时间间隔内对源表所做的净更改。 请注意,插入后又删除的行在函数返回的结果集中不会出现。 这是因为在查询窗口中先添加然后又删除的行在时间间隔内对源表不生成任何净更改。

注意

在运行此示例之前,必须先在 sys.sp_cdc_enable_table (Transact-SQL) 中运行示例 B,才能对表 HumanResources.Department启用 CDC。 在下面的示例中,HR_Department 是 CDC 捕获实例的名称,如 中指定的 sys.sp_cdc_enable_table

USE AdventureWorks2022;  
GO  
DECLARE @begin_time datetime, @end_time datetime, @from_lsn binary(10), @to_lsn binary(10);  
-- Obtain the beginning of the time interval.  
SET @begin_time = DATEADD(day, -1, GETDATE()) ;  
-- DML statements to produce changes in the HumanResources.Department table.  
INSERT INTO HumanResources.Department (Name, GroupName)  
VALUES (N'MyDept', N'MyNewGroup');  
  
UPDATE HumanResources.Department  
SET GroupName = N'Resource Control'  
WHERE GroupName = N'Inventory Management';  
  
DELETE FROM HumanResources.Department  
WHERE Name = N'MyDept';  
  
-- Obtain the end of the time interval.  
SET @end_time = GETDATE();  
-- Map the time interval to a change data capture query range.  
SET @from_lsn = sys.fn_cdc_map_time_to_lsn('smallest greater than or equal', @begin_time);  
SET @from_lsn = ISNULL(sys.fn_cdc_map_time_to_lsn('smallest greater than or equal', @begin_time), [sys].[fn_cdc_get_min_lsn]('HR_Department') );
SET @to_lsn = sys.fn_cdc_map_time_to_lsn('largest less than or equal', @end_time);  
  
-- Return the net changes occurring within the query window.  
SELECT * FROM cdc.fn_cdc_get_net_changes_HR_Department(@from_lsn, @to_lsn, 'all');  

另请参阅