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

Как я могу контролировать базу данных SQL Server на предмет изменений в таблице, не используя триггеры или каким-либо образом изменяя структуру базы данных? Моя предпочтительная среда программирования - .СЕТЬ и 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);

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

Они ведь случайно не поместили в свои строки метку времени последнего изменения, не так ли?

zmbq 04.11.2011 02:15

Для справки, если поддерживается версия SQL Server 2005 или новее. Я рассмотрю функцию Service Broker в SQL Server.

Marco Guignard 07.08.2019 18:37
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
148
2
65 385
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Почему вы не хотите использовать триггеры? Они хороши, если их правильно использовать. Если вы используете их как способ обеспечения ссылочной целостности, тогда они переходят от хороших к плохим. Но если вы используете их для мониторинга, они не считаются табу.

Иметь задание DTS (или задание, которое запускается службой Windows), которое выполняется с заданным интервалом. Каждый раз, когда он запускается, он получает информацию о данной таблице с помощью системных таблиц INFORMATION_SCHEMA и записывает эти данные в репозиторий данных. Сравните данные, возвращенные относительно структуры таблицы, с данными, возвращенными в предыдущий раз. Если он другой, значит, вы знаете, что структура изменилась.

Пример запроса для возврата информации обо всех столбцах в таблице ABC (в идеале перечисление только столбцов из таблицы INFORMATION_SCHEMA, которые вы хотите, вместо использования * select **, как я здесь):

select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'

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

Речь идет об изменениях в данных таблицы, а информация_schema содержит схему (определения столбцов) таблицы.

too 21.07.2014 12:15
Ответ принят как подходящий

Взгляните на команду КОНТРОЛЬНАЯ СУММА:

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

Это будет возвращать одно и то же число при каждом запуске, пока содержимое таблицы не изменилось. См. Мой пост об этом для получения дополнительной информации:

КОНТРОЛЬНАЯ СУММА

Вот как я использовал его для восстановления зависимостей кеша при изменении таблиц:
Зависимость кэша базы данных ASP.NET 1.1 (без триггеров)

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

LPains 26.05.2016 21:35

@LPains, не могли бы вы подробнее рассказать о своем заявлении?

petrosmm 25.07.2018 16:22

@petrosmm Я не уверен, что конкретно вы хотите, чтобы я уточнил, но я попробую. Представьте, что у вас есть таблица с несколькими сотнями записей, вы, по сути, генерируете целое число в качестве контрольной суммы, как часто это будет конфликтовать? В моем случае я делал это примерно с 10 таблицами, каждая из которых содержала сотни записей. У меня было хотя бы одно столкновение в день. Отметьте этот другой ответ stackoverflow.com/questions/14450415/…

LPains 27.07.2018 18:00

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

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

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

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

Здесь дикая догадка: если вы не хотите изменять таблицы сторонних разработчиков, можете ли вы создать представление, а затем установить триггер для этого представления?

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

К сожалению, CHECKSUM не всегда работает должным образом для обнаружения изменений..

Это только примитивная контрольная сумма и не вычисление циклического избыточного кода (CRC).

Следовательно, вы не можете использовать его для обнаружения всех изменений, например. грамм. симметричные изменения приводят к той же КОНТРОЛЬНОЙ СУММЕ!

E. g. решение с 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!

На самом деле это не ответ, это «ваше предложение не работает».

kristianp 19.01.2016 02:53

Это можно исправить для повторяющихся данных, используя ключевое слово DISTINCT перед BINARY_CHECKSUM. Есть еще несколько обсуждаемых ловушек здесь, но не совсем распространенные сценарии.

pblack 29.06.2016 19:22

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

Предоставьте документированный способ переноса этой информации в таблицу в SQL Server.

Martin Smith 07.10.2018 02:04

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