[解決済み] レコードの変更履歴を追跡するMySQLのオプション/機能はありますか?
質問
MySQLデータベースのレコードの変更点を記録できないか、という質問を受けました。つまり、あるフィールドが変更されたとき、新旧の比較とその日付がわかるようにするのです。これを行うための機能または一般的なテクニックはあるのでしょうか?
もしそうなら、次のようなことをしようかと考えていました。というテーブルを作成します。
changes
. と同じフィールドが含まれます。
マスター
しかし、実際に変更されたフィールドにのみ、oldとnewの接頭辞が付き、その後に
TIMESTAMP
を使用します。インデックスが作成され
ID
. このように
SELECT
レポートを実行し、各レコードの履歴を表示することができます。これは良い方法なのでしょうか?ありがとうございます。
解決方法は?
微妙なところですね。
ビジネス要件が「誰がいつ何をしたのか」というデータの変更を監査したい場合、通常は監査テーブルを使用します(Keethanjanが投稿したトリガーの例と同様です)。私はトリガーの大ファンではありませんが、これは比較的簡単に実装できるという大きな利点があります - 既存のコードはトリガーや監査について知る必要はありません。
もしビジネス要件が「過去のある日のデータの状態を教えてください」であれば、それは経時変化という側面がソリューションに含まれることを意味します。監査テーブルを見るだけで、データベースの状態を再構築することは可能ですが、それは困難であり、エラーが発生しやすく、また複雑なデータベースロジックでは扱いにくくなります。例えば、「月の初めの日に未払いの請求書があった顧客に送るべき手紙の宛先を知りたい」と考えた場合、半ダースの監査テーブルを調べなければならない可能性があります。
その代わりに、スキーマ設計に経時変化の概念を組み込むことができます(これはKeethanjanが提案する2番目のオプションです)。これは、ビジネスロジックと永続性のレベルで、アプリケーションを変更することになるので、些細なことではありません。
例えば、こんなテーブルがあったとします。
CUSTOMER
---------
CUSTOMER_ID PK
CUSTOMER_NAME
CUSTOMER_ADDRESS
で、時系列で追跡したい場合は、次のように修正します。
CUSTOMER
------------
CUSTOMER_ID PK
CUSTOMER_VALID_FROM PK
CUSTOMER_VALID_UNTIL PK
CUSTOMER_STATUS
CUSTOMER_USER
CUSTOMER_NAME
CUSTOMER_ADDRESS
顧客レコードを変更するたびに、レコードを更新する代わりに、現在のレコードのVALID_UNTILをNOW()に設定し、VALID_FROM(現在)およびNULL VALID_UNTILを持つ新しいレコードを挿入します。CUSTOMER_USER"ステータスを現在のユーザのログインIDに設定します(保持する必要がある場合)。顧客を削除する必要がある場合、CUSTOMER_STATUSフラグを使用してその旨を示します - このテーブルからレコードを削除することはできません。
そうすれば、ある日付の顧客テーブルの状態がどうであったか、つまり、住所はどうであったか、は常に知ることができます。住所はどうなっているのか、名前は変わっているのか?valid_fromとvalid_untilの日付が似ている他のテーブルと結合することで、全体像を歴史的に再構築することができるのです。現在の状態を調べるには、VALID_UNTILの日付がNULLであるレコードを検索します。
扱いにくい(厳密にはvalid_fromは必要ないが、クエリーが少し楽になる)。デザインもデータベースへのアクセスも複雑になります。しかし、世界の再構築をより簡単にすることができます。
関連
-
MySQLデータベース・インデックスの左端一致の原則
-
SQL集計、グループ化、ソート
-
mysqlインデックスが長すぎる特殊なキーが長すぎる解決策
-
MySQLでテーブルを削除します。親行が削除または更新できません: 外部キー制約に失敗しました。
-
[解決済み] Mysqlでidを使用してテーブルから多くの行を削除する
-
[解決済み] MySQLの複数行を1つのフィールドに連結することはできますか?
-
[解決済み] MySQLです。大きなVARCHARとTEXTの比較?
-
[解決済み] MySQLの重複レコードを検索する
-
[解決済み] phpMyAdminで外部キーを設定する?
-
[解決済み] CSVファイルをMySQLのテーブルにインポートするには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
MySQLにおけるorder byの使用方法の詳細
-
MySQLのNULLについて解説した記事
-
[解決済み】マルチパート識別子をバインドできない
-
mysql5.7のインストールと、無料・長期利用を目的としたNavicateの導入プロセスについて
-
MySQLの起動エラー:ERROR 2003 (HY000)。localhost'上のMySQLサーバーに接続できない(10061)
-
[解決済み] 1つのSQLクエリで複数のカウントを取得する方法は?
-
[解決済み] MySQLのAUTO_INCREMENTをリセットする方法
-
[解決済み] MySQLのクエリ結果をCSV形式で出力するにはどうすればよいですか?
-
[解決済み] MySQLで複数のカラムに一意制約を指定するには?
-
[解決済み】MySQLのテーブルが最後に更新されたのはいつなのか?