Проверьте наличие изменений в таблице SQL Server?
как я могу контролировать базу данных SQL Server для изменений в таблице без использования триггеров или изменения структуры базы данных в любом случае? Моя предпочтительная среда программирования - .NET и C#.
Я хотел бы иметь возможность поддерживать любой SQL Server 2000 SP4 или более новый. Мое приложение-это визуализация данных на болтах для продукта другой компании. Наша клиентская база исчисляется тысячами, поэтому я не хочу предъявлять требования, которые мы измените таблицу стороннего поставщика при каждой установке.
By "изменения в таблице" Я имею в виду изменения в табличных данных, а не изменения в структуре таблицы.
В конечном счете, я хотел бы, чтобы изменение вызвало событие в моем приложении, вместо того, чтобы проверять изменения с интервалом.
лучший курс действий, учитывая мои требования (без триггеров или модификации схемы, 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);
и сравнить возвращенные контрольные суммы с сохраненными значениями.
8 ответов:
взгляните на контрольную сумму команды:
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);
это будет возвращать одно и то же число каждый раз, когда он запускается до тех пор, пока содержимое таблицы не изменилось. Смотрите мой пост об этом для получения дополнительной информации:
вот как я использовал его для восстановления зависимостей кэша при изменении таблиц:
ASP.NET 1.1 зависимость кэша базы данных (без триггеров)
к сожалению контрольная сумма не всегда работает правильно, чтобы обнаружить изменения. Это только примитивная контрольная сумма и не вычисление CRC. Поэтому вы не можете использовать его для обнаружения всех изменений, например, симметричные изменения приводят к одной и той же контрольной сумме!
например, решение с
CHECKSUM_AGG(BINARY_CHECKSUM(*))
поставляет всегда 0 для всех 3 таблиц с различным содержанием!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!
Почему вы не хотите использовать триггеры? Они хороши, если вы используете их правильно. Если вы используете их как способ обеспечения ссылочной целостности, то это когда они переходят от хорошего к плохому. Но если вы используете их для мониторинга, они на самом деле не считаются табу.
Как часто вам нужно проверять наличие изменений и насколько велики (с точки зрения размера строки) таблицы в базе данных? Если вы используете
CHECKSUM_AGG(BINARY_CHECKSUM(*))
метод, предложенный Джоном, он будет сканировать каждую строку указанной таблицы. ЭлементNOLOCK
подсказка помогает, Но в большой базе данных вы все еще нажимаете каждую строку. Вам также нужно будет сохранить контрольную сумму для каждой строки, чтобы вы сказали, что она изменилась.вы рассматривали это с другой стороны? Если вы не хотите изменять схема для добавления триггеров (что имеет смысл, это не ваша база данных), вы рассматривали возможность работы с поставщиком приложения, который делает базу данных?
Они могут реализовать API, который обеспечивает механизм уведомления вспомогательных приложений, что данные изменились. Это может быть так же просто, как запись в таблицу уведомлений, в которой перечислены, какая таблица и какая строка были изменены. Это может быть реализовано с помощью триггеров или кода приложения. С твоей стороны, ти не имеет значения, ваша единственная забота будет сканировать таблицу уведомлений на периодической основе. Снижение производительности в базе данных будет намного меньше, чем сканирование каждой строки на наличие изменений.
трудная часть будет убеждать поставщика приложения реализовать эту функцию. Поскольку это может быть обработано полностью через SQL через триггеры, вы можете сделать большую часть работы для них, написав и протестировав триггеры, а затем приведя код к поставщику приложения. Имея поддержку поставщика триггеры, это предотвращает ситуацию, когда ваше добавление триггера непреднамеренно заменяет триггер, поставляемый поставщиком.
есть задание DTS (или задание, которое запускается службой windows), которое выполняется с заданным интервалом. Каждый раз, когда он запускается, он получает информацию о данной таблице с помощью системы information_schema для таблицы, и записывает эти данные в хранилище данных. Сравните возвращенные данные относительно структуры таблицы с данными, возвращенными в предыдущий раз. Если он отличается, то вы знаете, что структура изменилась.
пример запроса для возврата информация обо всех Столбцах в таблице ABC (в идеале перечислите только столбцы из таблицы INFORMATION_SCHEMA, которые вы хотите, вместо использования *select **, как я здесь):
select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'
вы будете отслеживать различные столбцы и представления INFORMATION_SCHEMA в зависимости от того, как именно вы определяете "изменения в таблице".
к сожалению, я не думаю, что там чистый способ сделать это в SQL2000. Если вы сузите свои требования до SQL Server 2005 (и более поздних версий), то вы находитесь в бизнесе. Вы можете использовать
SQLDependency
классSystem.Data.SqlClient
. Смотрите уведомления о запросах в SQL Server (ADO.NET).