SQL Serverテーブルへの変更を確認しますか?


142

トリガーを使用したり、データベースの構造を変更したりせずに、SQL Serverデータベースでテーブルの変更を監視するにはどうすればよいですか?私が好むプログラミング環境は.NETとC#です。

SQL Server 2000 SP4以降をサポートできるようにしたいのですが。私のアプリケーションは、他社製品のボルトオンデータ視覚化です。私たちの顧客ベースは数千にのぼるので、すべてのインストールでサードパーティベンダーのテーブルを変更するという要件を課す必要はありません。

「表への変更」表データへのI平均変化、テーブル構造に変わりはありません。

結局のところ、変更をアプリケーションで定期的にトリガーするのではなく、変更を定期的にチェックする必要があります。


私の要件(トリガーやスキーマの変更なし、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);

そして、返されたチェックサムを保存された値と比較します。


3
行に最後に変更されたタイムスタンプを付けていませんでしたか?
zmbq

参考までに、サポートされるバージョンがSQL Server 2005以降の場合。SQL ServerのService Broker機能について説明します。
Marco Guignard

回答:


97

CHECKSUMコマンドを見てください。

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

テーブルの内容が変更されていない限り、実行されるたびに同じ数が返されます。詳細については、これに関する私の投稿を参照してください:

チェックサム

これが、テーブルが変更されたときにキャッシュの依存関係を再構築するために使用した方法です
。ASP.NET1.1データベースのキャッシュの依存関係(トリガーなし)


2
チェックサムは最終的に失敗する可能性があり、失敗します。2つの異なるデータセットが同じチェックサムになることをシステムが受け入れる場合は、問題ありません。そのため、ほとんどのシステムではチェックサムから離れなければなりません
でした

@LPainsは、ステートメントについて詳しく説明できますか?
petrosmm 2018

1
@petrosmm具体的にどのようなことを具体的に説明してほしいのかはわかりませんが、試してみます。数百のレコードを持つテーブルがあり、本質的に整数をチェックサムとして生成することを想像してください。それはどれくらいの頻度で衝突するのでしょうか?私の場合、私はそれを約10のテーブルで、すべて数百のレコードで実行していました。1日に少なくとも1回は衝突がありました。この他の回答をチェックstackoverflow.com/questions/14450415/...
LPains

29

残念ながら、CHECKSUMは変更を検出するために常に適切に機能するとは限りません

これは基本的なチェックサムであり、巡回冗長検査(CRC)計算はありません。

したがって、これを使用してすべての変更を検出することはできません。たとえば、対称的な変更は同じチェックサムになります!

例:のソリューションでCHECKSUM_AGG(BINARY_CHECKSUM(*))は、コンテンツが異なる3つのテーブルすべてに対して常に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!


5
それは実際には答えではなく、「あなたの提案はうまくいきません」です。
kristianp

1
これは、BINARY_CHECKSUMの前にDISINCTキーワードを使用することで、重複データを修正できます。ここで説明する他のいくつかの落とし穴がありますが、厳密に一般的なシナリオではありません。
pblack

25

トリガーを使用したくないのですか?あなたがそれらを正しく使うなら、彼らは良いことです。参照整合性を強制する方法としてそれらを使用する場合、つまり、それらが良い状態から悪い状態に移行するときです。しかし、それらを監視に使用する場合、実際にはタブーとは見なされません。


20

変更を確認する必要がある頻度と、データベース内のテーブルのサイズ(行サイズに関して)はどれくらいですか。CHECKSUM_AGG(BINARY_CHECKSUM(*))Johnの提案する方法を使用すると、指定したテーブルのすべての行がスキャンされます。のNOLOCKヒントは役立ちますが、大規模なデータベース上で、あなたはまだ、すべての行をヒットしています。また、すべての行のチェックサムを保存して、1つが変更されたことを通知する必要があります。

これを別の角度から見ることを考えましたか?スキーマを変更してトリガーを追加したくない場合(これは理にかなっていますが、データベースではありません)、データベースを作成するアプリケーションベンダーとの協力を検討しましたか?

データが変更されたことをアクセサリアプリに通知するメカニズムを提供するAPIを実装することもできます。変更されたテーブルと行をリストする通知テーブルに書き込むのと同じくらい簡単です。これは、トリガーまたはアプリケーションコードを介して実装できます。あなたの側からは、tiは重要ではありません。あなたの唯一の懸念は定期的に通知テーブルをスキャンすることです。データベースのパフォーマンスへの影響は、すべての行の変更をスキャンするよりもはるかに少なくなります。

難しいのは、この機能を実装するようにアプリケーションベンダーを説得することです。これはトリガーを介してSQLで完全に処理できるため、トリガーを作成してテストし、コードをアプリケーションベンダーに提供することで、それらの作業の大部分を実行できます。ベンダーにトリガーをサポートさせることで、トリガーを追加するとベンダーが提供するトリガーが誤って置き換えられる事態を防ぎます。


18

残念ながら、SQL2000でこれを行うための明確な方法はないと思います。要件をSQL Server 2005(およびそれ以降)に絞り込むと、ビジネスに参入できます。SQLDependencyクラスはで使用できますSystem.Data.SqlClientSQL Server(ADO.NET)のクエリ通知を参照してください。


16

所定の間隔で実行されるDTSジョブ(またはWindowsサービスによって開始されるジョブ)を用意します。実行されるたびに、システムのINFORMATION_SCHEMAテーブルを使用して特定のテーブルに関する情報を取得し、このデータをデータリポジトリに記録します。テーブルの構造に関して返されたデータを、前回返されたデータと比較します。異なる場合は、構造が変更されていることがわかります。

テーブルABCのすべての列に関する情報を返すクエリの例(理想的には、ここで行うように* select **を使用する代わりに、必要なINFORMATION_SCHEMAテーブルの列のみをリストします):

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

「テーブルへの変更」を正確に定義する方法に応じて、さまざまな列とINFORMATION_SCHEMAビューを監視します。


2
問題はテーブルデータの変更についてであり、information_schemaにはテーブルのスキーマ(列定義)が含まれています。
あまりにも

13

ここで大まかな推測:サードパーティのテーブルを変更したくない場合は、ビューを作成して、そのビューにトリガーを設定できますか?


6

最終コミット日を確認してください。すべてのデータベースには、各コミットが行われたときの履歴があります。ACIDコンプライアンスの標準だと思います。


1
SQL Serverのテーブルにスコープこの情報取得の文書化の方法を提供してください
マーティン・スミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.