Вопрос:

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

sql sql-server datatable rdbms

53601 просмотра

9 ответа

980 Репутация автора

Как я могу отслеживать изменения в таблице базы данных 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);

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

Автор: TimM Источник Размещён: 01.08.2008 12:35

Ответы (9)


26 плюса

45692 Репутация автора

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

Автор: Nick Berardi Размещён: 01.08.2008 01:07

18 плюса

29198 Репутация автора

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

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

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

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

Автор: Yaakov Ellis Размещён: 01.08.2008 02:06

94 плюса

40011 Репутация автора

Решение

Посмотрите на команду CHECKSUM:

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

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

СУММА

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

Автор: Jon Galloway Размещён: 02.08.2008 05:20

20 плюса

3292 Репутация автора

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

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

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

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

Автор: Chris Miller Размещён: 03.08.2008 01:59

13 плюса

85746 Репутация автора

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

Автор: Orion Edwards Размещён: 05.08.2008 01:12

18 плюса

6295 Репутация автора

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

Автор: caryden Размещён: 06.08.2008 01:54

30 плюса

301 Репутация автора

К сожалению, CHECKSUM не всегда работает правильно, чтобы обнаружить изменения . Это только примитивная контрольная сумма и не вычисляется 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!<p></p>

<p>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!</p>

<p>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!
</p>

Автор: BitLauncher Размещён: 30.03.2011 12:07

6 плюса

390 Репутация автора

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

Автор: ECE Размещён: 24.07.2014 04:58

0 плюса

1 Репутация автора

SELECT CHECKSUM_AGG (BINARY_CHECKSUM (*)) ОТ sample_table WITH (NOLOCK);

Автор: Tiez Размещён: 13.03.2019 10:38
Вопросы из категории :
32x32