<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)。
语法
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为 binary(10)。
仅 cdc 中的 行。[capture_instance]_CT 结果集中包含值 __$start_lsn大于或等于 from_lsn 的更改表。
to_lsn
LSN,它表示要包含在结果集中的 LSN 范围的高端点。 to_lsn为 binary(10)。
仅 cdc 中的行。[capture_instance]_CT结果集中包含值小于或等于 from_lsn 或等于 to_lsn 的值的 __$start_lsn 更改表。
<> row_filter_option ::= { all | all with mask | all with merge }
控制元数据列的内容和结果集中所返回的行的选项。 可以是下列选项之一:
全部
返回对行的最终更改的 LSN,以及在元数据列中应用该行所需的操作 __$start_lsn 和 __$operation。 列 __$update_mask始终为 NULL。
all with mask
返回对行的最终更改的 LSN,以及在元数据列中应用该行所需的操作 __$start_lsn 和 __$operation。 此外,当更新操作返回 (__$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
使用 DELETE 显示初始 UPDATE 命令,然后改为 INSERT 命令。 此行为是跟踪更改前后密钥所必需的。
如果提供的 LSN 范围在调用或调用cdc.fn_cdc_get_all_changes_<capture_instance>
cdc.fn_cdc_get_net_changes_<capture_instance>
时不适用,则预期会出现错误 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
此错误应由开发人员处理。
示例
以下示例使用函数 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');