MS Accessの "レコードの変更"ログ

フォーム上でレコードが削除または更新されるたびに、古い値を履歴テーブルに保存したい(Revisedと呼ぶ)。私は次のことをしなければならないと思う:

For record changes:

  • BeforeUpdateイベントを使用してどこかの(コレクション配列かレコードセット - 改訂されたテーブル - まだ保存せずに)データを保存しますか?
  • AfterUpdateイベントを使用して、そのデータをRevisedテーブルに追加/保存する

For Deletions:

  • OnDeleteイベントを使用してデータを保存します。フォーム(実際にはサブフォーム)がデータシートビューにあるので、一度に複数のレコードを削除することができます。
  • AfterDelConfirmを使用して、そのデータを改訂表に追加します。

このための手がかり、コメント、またはリンクはありますか?
これはすべて現時点では「純粋なアクセス」(SQL Serverなし)にあります。 どうもありがとう !


編集:いつものように、適切に質問すると私のアイデアを掴む:

オプション1

BeforeUpdateまたはOnDeleteを使用してSQL文を作成し、AfterUpdateまたはAfterDelConfirmを使用してSQL文を実行します。しかし、それは複数の削除のために動作しませんか?

オプション2

改訂されたレコードセットがフォームレベルで定義されている場合は、レコード「前」を挿入しますが、「後」を更新します。再度、複数の削除に関する問題。

2
あなたの問題について考えると、元のINSERTを追跡することによって、各更新プログラムの古い値または新しい値に従う必要がなくなります。最初のINSERTは元の '古い'値を返し、最後のUPDATEは最新の値を返します。
追加された 著者 Philippe Grondier,
通常は(そして管理しやすい)SQL INSERT、UPDATE、またはDELETEのログを保持することです。しかし、私はあなたがコントロール\フォームにバインドされているレコードセットでここで働いていると思いますか?ところで、あなたは正確に何を追跡したいですか?すべてのテーブルの変更?いくつかのテーブル?特定のフィールド?ユーザーあたり?
追加された 著者 Philippe Grondier,
@Philippe G:1つの特定のテーブルに対してすべての変更(削除または更新、挿入を追跡する理由はないと思う)を追跡したい
追加された 著者 Patrick Honorez,
アクティブなレコードのコンセプトについて:本当に良いですが、ブール値のフィールドにはインデックスを付けるメリットがほとんどないので、すべてのクエリで Active = True
追加された 著者 Patrick Honorez,
それは "削除された"という概念を "アクティブ"なようなものに再定義するのに役立つでしょうか?フォームのレコードソースに WHERE active = True が含まれていて、実際に削除が実際に active = False になることが考えられます。まだ存在しますが、フォームには表示されません。
追加された 著者 HansUp,
いくつかの参考文献: support.microsoft.com/kb/197592 ofnisystems.com/index.htm (tek-tips.com phvで引用)
追加された 著者 Fionnuala,
IsActive フィールドの代わりに DateDeleted フィールドを使用できます。もう少しストレージ容量を増やしますが、インデックスを作成して追加情報を提供することもできます(ユーザーが何をしているかを正確に把握しようとするといつか役立つかもしれません)。すべてのクエリは、 Active = True ではなく DateDeleted Is Null の条件になります。
追加された 著者 mwolfe02,
実際にレコードを削除するのではなく、削除されたレコードを「マークする」というアイデアのために+1から@ HansUp。ストレージが安くなるにつれ、私は本当に削除すべきものを再考しています。あなたがパフォーマンスを維持できる限り、「ああ、あなたはそれらのレコードを削除するつもりはなかったのですか?実際、はい、あなたのために戻すことができます。
追加された 著者 mwolfe02,
前もって考慮すべきもう一つのことは、この監査証跡をユーザーに提示するかどうかです。柔軟性があり、簡潔で、ユーザーが理解しやすいソリューションで終わることは非常に難しいです。一般的には、そのリストから最も重要な属性を2つ選んで3番目の属性を犠牲にしなければなりません。その決定は設計全体に影響するため、それを前もって把握することが重要です。
追加された 著者 mwolfe02,

3 答え

私は、いくつかの異なるプロジェクトでAllen Browneのアプローチのバリエーションをうまく使用しました。詳細については、彼のウェブサイトをチェックしてください:

監査ログの作成

彼のソリューションは、一時テーブルと4つの汎用関数呼び出しを使用して、複数の削除で問題を処理します。

3
追加された
優れたアレンブラウン!彼のサイトは金鉱です!
追加された 著者 Patrick Honorez,

最近私が検討したが、実際に実装する機会がなかったもう1つのアプローチは、トランザクションを使用して変更追跡を実行することです。基本的なアルゴリズムは次のとおりです。

  1. use BeginTrans on the workspace prior to making any changes
  2. in the OnDelete event
    • perform the deletions in code executing Delete queries against the workspace from step 1
    • add a record to your change auditing table
  3. in the BeforeDelConfirm event
    • set Cancel = True
    • display your own Confirmation dialog
    • if user confirms then CommitTrans on workspace
    • otherwise Rollback the transaction on the workspace

更新/挿入のための同様のアプローチ。これは、一時テーブル/配列/コレクションなどの必要性を避けるだろうが、私はすべてを十分に考えていない。悪魔は細部にいるかもしれない。

3
追加された
+1。非常に面白いアイデア!!
追加された 著者 Patrick Honorez,
ありがとうございます@ mwolfe02 ... "削除フォームイベントは、削除されるレコードごとに1回実行されます。"私は何とか自分自身がそうでなければ確信していました。 :-(
追加された 著者 HansUp,
私は自分の考えをうまく表現していないか、それに対処しています。いずれにせよ、私の悪い。ユーザーが現在のレコードだけを削除している場合は、どのレコードを識別するのが簡単です。次に、単純な削除の代わりに、またはそれに加えて、何かを行います。ただし、1回の削除操作で複数のレコードが選択されている場合は、そのレコードを識別する必要があります。それは私を嫌う挑戦です。 IIRCを使用すると、フォームのSelTopとSelHeightを検査できますが、フォーカスが別のコントロールに移動したときには使用できなくなります。選択された行を識別する簡単な柔軟な代替方法はありますか?
追加された 著者 HansUp,
両方のあなたの提案の+1。私は、データシートビューで選択された複数のレコードが1回の操作として削除された場合と統合するという課題に取り組んでいます。その側面に関するどんな考えですか?
追加された 著者 HansUp,
実際には両方のソリューションが問題に対処しています。 Allenのサイトから:フォームのDeleteイベントで、以下のコードはレコードのコピーをtempテーブルに書き込みます。フォームのAfterDelConfirmイベントでは、Accessによって提供されたStatus引数が削除の進行を示す場合にのみ、これらのレコードが真の監査テーブルにコピーされます。その後、一時表のコピーが削除されます。
追加された 著者 mwolfe02,
実際、この答えのアルゴリズムは、同じ問題に対処することを意図しています。 OnDeleteでCancel = Trueを設定すると、削除された作業がバインドされたフォームから離れているため、開いているトランザクションに対して実行される可能性があります。これにより、ユーザがその削除をキャンセルした場合に、トランザクション(削除履歴自体と追加履歴の両方)をロールバックすることができます。
追加された 著者 mwolfe02,
編集:私はこれをテストし、すべての削除イベントがキャンセルされた場合、BeforeDelConfirm/AfterDelConfirmイベントが実行されないことを認識しました。そこで、Cancel = TrueをBeforeDelConfirmイベントに移動しました。
追加された 著者 mwolfe02,
もう1つの問題は、BeginTransを実際に呼び出すときです。私の答えでは、一見してわかりましたが、イベントの順序は削除 BeforeDelConfirm AfterDelConfirm です。つまり、最初のDeleteイベントの前にBeginTransへのイベントはありません。私が言ったように、悪魔は細部にいるかもしれない...
追加された 著者 mwolfe02,
削除フォームイベントは、削除される各レコードに対して1回実行されます。したがって、ユーザーが5レコードを選択してDeleteキーを押すと、Form_Deleteが5回呼び出され、Form_BeforeDelConfirmが1回呼び出された後、Form_AfterDelConfirmが1回呼び出されます。すべてのForm_Delete( Cancel = True )をキャンセルすると、Form_BeforeDelConfirmが実行されなくなる可能性があります。同様に、Form_BeforeDelConfirmをキャンセルすると、Form_AfterDelConfirmが実行されなくなる可能性があります。
追加された 著者 mwolfe02,
AccessがBeforeDelConfirmイベントとAfterDelConfirmイベントの間の各レコードの2番目のDeleteイベントを発生させるといいでしょう。このようなことは扱いやすくなります。
追加された 著者 mwolfe02,

複数のテーブルに対して実装できる「簡単で簡単な」ソリューションは、次のようなトラッキングテーブルを持つことです。

Track_Table
==================================================
id_track as primary key
id_table as name of the table which has been updated
id_primaryKey as the record identifier (the PK of the updated record)
changeType, being either DEL or UPDATE
changeDate, as dateTime value
fieldName, as text
oldValue, as text or memo
newValue, as text or memo

更新を行ったユーザーを特定する必要がある場合は、

userId

あなたのテーブルに...

その後、選択されたフォームのbeforeUpdateおよびafterUpdateイベントで呼び出される汎用の「更新前」および「更新後関数」を作成できます。 beforeUpdate関数は変数に古い値を格納し、afterUpdate関数は欠落したデータを取り込み、トラックテーブルに新しいレコードを挿入します。

対応するテーブル名とフィールド名を見つける方法を見つける必要があります。ビューまたはフィールドエイリアスを使用してフォームにデータを表示している場合、これは難しい場合があります。

もちろん、従うすべてのテーブルには、レコードレベルで変更を追跡できるように、主キーが必要です。複数のフィールドに設定されたPKは確実に問題になります....

oldValuesとnewValuesは、テキストまたはメモフィールドに保存できるようにテキストとして変換する必要があります

0
追加された