あなたが説明していることは「監査履歴」と呼ばれることもあります。これは、単一の非正規化されたテーブルを使用して実装されることがよくありますが、強い型付けを失うと、多くのDB純粋主義者が反対します。
テーブルは次のようになります。
AuditTable( EventId bigint, DateTime datetime, Subject nvarchar, Table varchar, Column varchar, TablePK bigint, OldValueInt bigint nullable, OldValueStr nvarchar nullable )
-- add more nullable columns for more types, if necessary
ユーザーのレピュテーションが増加するなど、値が変更されるたびに、次のようにこのテーブルに行を追加します。
INSERT INTO AuditTable( Now(), N'User reputation increased', 'Users', 'Reputation', @userId, 100 )
新しい(つまり現在の)値は実際のテーブル行にあるため、古い値(変更前の値)のみを保存する必要があります。
監査テーブルへの追加は、SQLServerテーブルトリガーを使用して完全に自動的に実行できます。
ユーザーのレピュテーション履歴を表示するには、次のようにします。
SELECT * FROM AuditTable WHERE Table = 'Users' AND Column = 'Reputation' AND TablePK = @userId
さて、私が言ったように、この設計は、ユーザーが簡単にアクセスできる履歴を維持するのではなく、監査のためのものです。これらは欠点です。
- テーブルにセマンティックなインデックスを付けることはできないため、ルックアップとリストは常に遅くなります
- データベースのメタデータを文字列として保存しているため、多くのオーバーヘッドが発生します
- 参照整合性はありません(これは、元のテーブルを再アーキテクチャ化した場合、たとえば、UsersテーブルからReputationフィールドを削除した場合に、データが残るという点で良いことです)
より「純粋」になりたい場合は、構築する履歴追跡を直接サポートするテーブル構造を実際に設計する必要があります。すべてのフィールドに履歴テーブルを作成する必要はありません。Stackoverflowでさえすべての履歴を保存するわけではありません。例えば:
UserReputationHistory ( UserId bigint, ReputationChange int, DateTime when, Subject nvarchar )
もちろん、これらの異なるFooHistoryテーブルを維持する必要があるため、コードが複雑になります。
メンバーの参加日など、コメントする元の質問の他の項目には履歴テーブルは必要ありません。これDateJoined
は、メンバー自身のDB行のフィールドから取得できます。