【问题标题】:HOWTO: Interpret the MSSQL CDC "__$update_mask" field如何:解释 MS SQL CDC“__$update_mask”字段
【发布时间】:2015-03-04 16:21:11
【问题描述】:

由于我在如何使用“$update_mask”字段时遇到了很大的困难(出于性能原因,我不想调用 fn_cdc_is_bit_set),这里是 C# 代码:

  • updateMask 是 CDC“fn_cdc_get_all_changes_[table]”查询中“__$update_mask”字段的内容
  • colOrdinal 是您要从中获取更改标志的列的序号(使用“n_cdc_get_column_ordinal”检索此值)

结果是“hasChanged”标志。如果该字段在更新中已更改,则设置为 true。

请注意,这适用于 SQL Server 2008 和 2012,但可能不适用于未来的版本。

byte[] updateMask = this.UpdateMask;
        unchecked
        {
            byte relevantByte = updateMask[(updateMask.Length - 1) - ((colOrdinal - 1) / 8)];
            int bitMask = 1 << ((colOrdinal - 1) % 8);
            var hasChanged = (relevantByte & bitMask) != 0;

            return hasChanged;
        }

【问题讨论】:

  • 我会将其重新格式化为一个问题,然后将您的问题的答案放在下面。可以回答您自己的问题。
  • 顺便说一句,我在 clr 中使用了您的方法来返回以逗号分隔的字符串更改的列名。效果很好。 dba.stackexchange.com/questions/35936/…

标签: sql-server cdc


【解决方案1】:

只需使用BitArray 即可获取已更改列的序号索引。反转掩码并添加到BitArray,所有设置为true的数组值都是对应索引处的更改列。

byte[] updateMask = this.UpdateMask;  
Array.Reverse(updateMask);
BitArray columnBits = new BitArray(bitmask);

// To match your code sample, you can just check if the column bit is set at the ordinal.
bool hasChanged = columnBits[colOrdinal];

// You could loop and get the column indexes like this as well.
for (int i = 0; i < columnBits.Length; i++)
{
  // If the bit is set to true then the column at the same index was modified.
  if (columnBits[i])
  {
    // Do something with modified column at index 'i'.
  }      
}

我已尝试使代码示例尽可能简单易读。记得先检查数组索引是否存在等等。

【讨论】:

    【解决方案2】:

    我对此不是 100% 确定,但很可能$update_mask 中的值是COLUMNS_UPDATED() 在触发器内返回的值。您可以在此处获取有关如何解释该值的详细信息:http://msdn.microsoft.com/en-us/library/ms186329.aspx

    【讨论】:

    • 格式似乎与 COLUMN_UPDATED 的格式不完全相同。相反,updateMask 中的字节似乎以某种相反的顺序排列。这就是为什么会有这条有趣的线“updateMask[(updateMask.Length - 1) - ((colOrdinal - 1) / 8)];”在我的代码中。
    【解决方案3】:

    我遇到了同样的问题。我有多次调用函数 sys.fn_cdc_is_bit_set 的过程,甚至编译该过程也需要几分钟,而且执行速度也非常慢。当我用手动掩码解析替换函数 sys.fn_cdc_is_bit_set 时,它的工作速度要快得多。 substring([$update_mask],len([$update_mask]) - (([ColumnOrder]-1)/8),1) & power(2,([ColumnOrder]-1) 的情况%8) > 0 然后 1 else 0 结束

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-18
      • 1970-01-01
      • 2013-04-27
      • 2017-01-02
      • 2018-02-19
      • 1970-01-01
      • 2021-02-21
      相关资源
      最近更新 更多