HOWTO: интерпретировать поле MSSQL CDC "__$update_mask"

Поскольку у меня были большие трудности при работе с полем "$update_mask" (я не хочу вызывать fn_cdc_is_bit_set по соображениям производительности), вот код C#:

  • updateMask - это содержимое поля "__$update_mask" из запроса CDC "fn_cdc_get_all_changes_[table]"
  • 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;
        }

3 ответа

Просто используйте 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'.
  }      
}

Я постарался сделать пример кода максимально простым и читабельным. Не забудьте проверить, существуют ли сначала индексы массива и т. Д.

Я не уверен на 100% в этом, но, скорее всего, значение в $update_mask это тот, который COLUMNS_UPDATED() возвращается внутрь триггера. Вы можете получить подробную информацию о том, как интерпретировать это значение здесь: http://msdn.microsoft.com/en-us/library/ms186329.aspx

У меня такая же проблема. У меня была процедура с многократным вызовом функции sys.fn_cdc_is_bit_set, и даже компиляция этой процедуры заняла несколько минут, и выполнение также было ужасно медленным. Когда я заменил функцию sys.fn_cdc_is_bit_set на ручной анализ маски, она работала намного быстрее. случай, когда подстрока ([$ update_mask], len ([$ update_mask]) - (([ColumnOrder] -1) / 8), 1) & power (2, ([ColumnOrder] -1)% 8)> 0, затем 1 еще 0 конец

Другие вопросы по тегам