Проверить наличие изменений в таблице SQL Server?


Answers

К сожалению, CHECKSUM работает неправильно, чтобы обнаружить изменения . Это всего лишь примитивная контрольная сумма и вычисление CRC. Поэтому вы не можете использовать его для обнаружения всех изменений, например, симметричные изменения приводят к тому же CHECKSUM!

E. g. решение с CHECKSUM_AGG(BINARY_CHECKSUM(*)) обеспечивает всегда 0 для всех трех таблиц с различным контентом!


SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM 
(
  SELECT 1 as numA, 1 as numB
  UNION ALL
  SELECT 1 as numA, 1 as numB
)  q
-- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 1 as numA, 2 as numB UNION ALL SELECT 1 as numA, 2 as numB ) q -- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 0 as numA, 0 as numB UNION ALL SELECT 0 as numA, 0 as numB ) q -- delivers 0!

Question

Как я могу контролировать базу данных SQL Server для изменений в таблице без использования триггеров или каким-либо образом изменить структуру базы данных? Моя предпочтительная среда программирования - .NET и C #.

Я хотел бы иметь возможность поддерживать любой SQL Server 2000 SP4 или новее. Мое приложение - это визуальная визуализация данных для другой компании. Наша клиентская база находится в тысячах, поэтому я не хочу вводить требования, которые мы изменяем таблицу сторонних поставщиков при каждой установке.

Под «изменениями к таблице» я имею в виду изменения в табличных данных, а не изменения в структуре таблицы.

В конечном счете, я хотел бы, чтобы изменение инициировало событие в моем приложении, вместо того, чтобы проверять изменения с интервалом.

Лучший способ действия с учетом моих требований (без триггеров или модификации схемы, SQL Server 2000 и 2005), похоже, заключается в использовании функции BINARY_CHECKSUM в T-SQL . Способ, которым я планирую реализовать, таков:

Каждые X секунд выполняется следующий запрос:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);

И сравните это с сохраненной стоимостью. Если значение изменилось, перейдите в таблицу по строкам, используя запрос:

SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);

И сравните возвращенные контрольные суммы с сохраненными значениями.




К сожалению, я не думаю, что в SQL2000 есть чистый способ сделать это. Если вы ограничиваете свои требования к SQL Server 2005 (и более поздним), то вы находитесь в бизнесе. Вы можете использовать класс SQLDependency в System.Data.SqlClient . См. Уведомления о запросах в SQL Server (ADO.NET) .




Как часто вам нужно проверять изменения и насколько большими (с точки зрения размера строки) являются таблицы в базе данных? Если вы используете метод CHECKSUM_AGG(BINARY_CHECKSUM(*)) предложенный Джоном, он сканирует каждую строку указанной таблицы. Подсказка NOLOCK помогает, но в большой базе данных вы все равно нажимаете на каждую строку. Вам также нужно будет хранить контрольную сумму для каждой строки, чтобы вы сказали, что она изменилась.

Считаете ли вы, что это происходит под другим углом? Если вы не хотите изменять схему для добавления триггеров (что имеет смысл, это не ваша база данных), считаете ли вы, что работаете с поставщиком приложений, который делает базу данных?

Они могут реализовать API, который обеспечивает механизм уведомления приложений-приложений, которые изменили данные. Это может быть так же просто, как записать в таблицу уведомлений, в которой перечислены, какая таблица и какая строка были изменены. Это может быть реализовано с помощью триггеров или кода приложения. С вашей стороны, ti не имеет значения, ваша единственная проблема - сканирование таблицы уведомлений на периодической основе. Производительность, попадающая в базу данных, будет намного меньше, чем сканирование каждой строки для изменений.

Жесткая часть будет убеждать поставщика приложений в реализации этой функции. Поскольку это может быть полностью обработано через SQL через триггеры, вы можете сделать основную часть работы для них, написав и протестировав триггеры, а затем доведя код до поставщика приложения. Предоставляя поставщику триггеры, он предотвращает ситуацию, когда добавление триггера непреднамеренно заменяет триггер, предоставляемый поставщиком.




Проверьте последнюю дату фиксации. Каждая база данных имеет историю, когда выполняется каждая фиксация. Я считаю, что это стандарт соответствия ACID.