データベースエントリの変更履歴を取得する方法


21

データベースエントリ(データ)のバージョン管理を許可する方法は何ですか?

記事の変更を元に戻すコンテンツ管理システムの機能を考えてください。

彼らの長所/短所は何ですか?


1
何を正確にバージョン管理しますか?スキーマまたはデータ?
-tdammers

1
データをバージョン管理したい。CMSの例に滞在するには、バージョンの言うことができます記事を
matcauthon

Datomicを調べてください。
dan_waterworth

回答:


19

基本的に2つのアプローチがあります。以前のすべての値が格納されている監査テーブル、またはテーブルの一部として開始/終了日を含める、すべての更新は古いレコードを閉じるときに新しいレコードを作成します。

更新:SQL SERVER 2016はこれをデザインパターン/テーブルタイプとしてサポートします— https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-2017


4
したがって、最初のアプローチはよりスケーラブルかもしれません。「アーカイブされた」データはめったにアクセスされないため、データベース設計を最適化できます。そして、作業テーブルには小さな続けます。複雑さに応じて、差分のみを保存することも可能です。mementoパターンを使用することをお勧めしますか?
matcauthon

1
それは使用方法に依存しますが、トリガーを使用してテーブルにデータを入力し、ロールバックする対象と範囲を選択する方法を提供すれば十分かもしれません。
jmoreno

答えにタイプミスがあります(パターンはパターンでなければなりません)
geocodezip

7

1つのアイデアは、「挿入専用データベース」を使用することです。基本的な考え方は、行のデータを削除または更新しないことです。

追跡する必要がある各テーブルには、2つのdatetimefromとがありtoます。それらNULLはそれぞれの値で始まります(時間の始まりから終わりまで)。行を「変更」する必要がある場合は、新しい行を追加すると同時にto、前の行のをNowfrom追加する行のを更新しNowます。

詳細については、次を参照してください。

この手法はAuditTrail、レガシーデータを管理するために呼び出され、変更履歴を保存します。

この性質の質問はすでに投稿されているようです:


悲しいことに、その質問は削除されたように見えます:(
ダグラスGaskell

問題ありません、ここにリンクがあります。リンクの
ユスボフ

2

各テーブルにトリガーを使用し、_historyにデータを保持する(または任意の名前を付ける)ことができ、メインテーブルでの挿入、更新、削除のたびにトリガーがトリガーされ、このテーブルに詳細を保存できると思います。使用している場合は、SQLiteデータベースでも使用できます。

このメカニズムは、大規模なプロジェクトにも役立ちます。この表では、変更を行ったユーザーの情報と変更のタイムスタンプを記録できます。その後、要件に一致する任意のタイムスタンプにテーブルを復元できます。

すべてのデータベースには、トリガーを記述およびコーディングする独自の方法があります。SQLiteを使用している場合、構文についてはSQLite.orgにアクセスしてください。他のデータベースについては、公式サイトをご覧ください。


1

おそらくSqlite dbエンジンをご存知でしょう。データベース全体が単一のファイルに保存されます。apiは仮想ファイルシステムもサポートしているため、基本的には、特定のファイルオフセットで読み取りおよび書き込み操作に応答するだけで、どこでも任意の形式でストレージを整理できます。これの可能なアプリケーションは、暗号化、圧縮などです。コンテナレイヤーがデータベース、sqlまたはsqliteファイル形式について何も知らず、xReadおよびxWriteコールバックに従うだけであるということの最も良い部分です。

アイデアの1つは、タイムマシン機能を実装することでした。したがって、xWrite操作は、「元に戻す」履歴で上書きするすべてのセグメントを保存し、ユーザーは過去の日付を選択して、dbに含まれる内容を確認できます(おそらく読み取り専用モード)。まだ実用的な例はありませんが(sqliteメーリングリストで議論されました)、おそらく他のエンジンがVFS APIを提供しているため、同様のことが可能です。そして、一度実装すれば、どんな複雑なデータベース構造とも互換性があるはずです。


このアプローチは、大規模なプロジェクトに対してスケーラブルだと思いますか?
matcauthon

これにより、大きなデータの変更に対して大きなデータオーバーヘッドが追加される可能性があると思います(明らかに、すべての変更を保存する必要がありますが、古いバージョンの圧縮は役立ちます)。それとは別に、スキーマの観点からは、2つのテーブルで機能する限り、20で機能します。
マクシー

1

データベースエントリのバージョン管理に使用する方法は、監査テーブルを使用することです。テーブルには、次の行に沿ったスキーマがあります。

Seq      - Int      ' Unique identifier for this table
Event    - Char     ' Insert / Update / Delete
TblName  - Char     ' Table that had field value changed
FldName  - Char     ' Field that was changed
KeyValue - Char     ' delimited list of values for fields that make up the PK of table changed
UsrId    - Char     ' User who made the change
OldValue - Char     ' Old value (converted to character)
NewValue - Char     ' New value (converted to character)
AddTs    - DateTime ' When the change was made

その後、追跡するテーブルの挿入/更新/削除のトリガーがあります。

長所:

  • すべてのデータは1つのテーブルにあります
  • テーブル内のすべてのフィールドまたは特定のフィールドを追跡するように設定できます
  • テーブルの各フィールドに簡単にバージョン管理を表示

短所:

  • 1つのテーブルにすべての監査情報があると、非常に多くのレコードが作成されます
  • たくさんのトリガーが必要

0

現在、このバージョンを作成しています。レコードごとに、挿入日、変更日、およびアクティブレコードブール値フラグがあります。最初の挿入の場合、挿入日と変更日は両方ともNow()に設定され(この例はAccessにあります)、アクティブレコードフラグはに設定されtrueます。そのレコードを変更する場合、ユーザーが変更しているフィールドを変更して、すべてを新しいレコードにコピーし、挿入日を元の日付のままにして、変更日をNow()に変更します。次に、元のレコードのActive Recordフラグをにfalse、新しいレコードをに切り替えtrueます。また、元のレコードのIDを保存するModifiedRecordsParentIDのフィールドもあります。

その後、クエリする必要がある場合でも、レコードを返すことができActiveRecord = true、最新の情報のみを取得できます。


ActiveRecordフラグは必要ありません。MAX(*)行は常に現在のレコードでなければなりません。前のバージョンに復元すると、単にその行がテーブルに再び挿入されます。
反転

選択を機能させる方法がわかりませんでしたが、今あなたがこれを呼んでいるので、私はそれについて考えており、アイデアを持っています、うーん
ブラッド

通常、MAX(column_name)はテーブルの列の最大値を選択します。行全体を選択するには、単純な方法でselect top 1 order by id descending行います。
反転

ええ、それは単純な単一のレコードで機能しますが、私のテーブルは、一度に選択する必要があるが、個別に変更することができる子レコードのコレクションでした。もう少し複雑です。
ブラッド

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.