web-dev-qa-db-ja.com

データの整合性を維持するための請求書への個人データの保存

人の住所などの請求書データを保存したい。ただし、問題は住所が時間の経過とともに変化する可能性があることです。たとえば、誰かが引っ越して自分の住所を変更します。一部の請求書で参照されているデータを変更できないため、このようなデータを保存する問題が発生します。

私は3つのテーブルを持っています:AddressInfo(StreetAddressなどを含む)、PersonAddressInfoと1対多の関係にあり、Invoiceテーブルです。

これには2つの解決策がありますが、どちらの方向が正しい方向であるかわかりません。

  • AddressInfoを作成してソフト削除可能にし、IsActiveまたはIsDeletedなどの列を追加して、Invoiceテーブルがこのアドレス情報をIDで参照できるようにします。私のアプリケーションを使用せずに誰かがこのデータを直接変更しない限り、同じままであることが保証されています。

    したがって、誰かが自分のアドレスを変更すると、私は現在のアドレスをソフト削除(おそらく、ソフト更新と呼ばれるべきですか?)し、古いレコードをまったく変更せずに新しいアドレスを追加します。汚染を防ぐために、最初に請求書で参照されているかどうかを確認することをお勧めします。

    私のInvoiceテーブルは次のようになります。

    | InvoiceId | AddressInfoId |

  • 必要な列をAddressInfoからInvoiceテーブルに追加します。新しい請求書を作成するたびにデータをコピーする必要があります。アドレスが頻繁に変更されないため、レコードが重複してデータベースが少し汚染されます。

    私のInvoiceテーブルは次のようになります(非常に単純化されています)。

    | InvoiceId | StreetAddress |

この特定の問題を解決するデータベース(おそらくいくつかのERPソフトウェア))の経験はありますか?


興味深い読み物:

https://martinfowler.com/eaaDev/timeNarrative.html

5
Konrad

私が見た解決策は、住所データをInvoiceHeaderテーブルにコピーすることです。これは冗長性ですが、害はありません*。請求書の住所は後で変更できないため、更新の異常は発生しません。

製品価格データをInvoiceDetailテーブルにコピーすることについても同様のことが言えます。

*更新の異常は、有害な冗長性に対してのみ発生します。それでも、顧客の住所が後でcustomerテーブルで変更されても、InvoiceHeaderテーブルで変更されていない場合、それらは冗長ではなくなります。

9
Walter Mitty

ソリューション#1は問題ありません。 Addressesテーブルを維持することは正規化されたソリューションであり、CustomerテーブルとInvoiceテーブルを小さく維持するという利点があります。おそらく、アドレスをソフト削除する必要すらありません。誰かが顧客の現在の住所を必要とする場合は、Customer.AddressIDで調べます。 Addressesテーブルは読み取り専用にすることができます。

お客様が以前に行った請求書とは関係なく、住所が変更されたときに追跡する場合は、フィールドCustomerAddressHistoryCustomerID、およびAddressIDを含む新しいDateEffectiveテーブルを作成できます。 AuthorityIDフィールド(誰が変更を行ったかを反映するため)や、DateObsoleteフィールドも必要になる場合があります。 CustomerID WHERE DateObsolete IS NULLの一意のインデックスを使用すると、顧客の現在の住所にすぐにアクセスできるため、顧客テーブルからAddressIDフィールドを削除できます。

Invoicesテーブルには、AddressIDフィールドがあります。 Addressesテーブルには、これまでに使用されたすべてのアドレスが格納されます。

3
  1. 現状のまま、AddressInfoIDで請求書を参照してください。
  2. IsCurrentビット列をAddressInfoテーブルに追加します。
  3. 顧客が住所を変更すると、元の住所レコードは保持されますが、IsCurrent値が0に変更されます。
  4. IsCurrent = 1の新しいAddressInfoレコードを追加します
  5. すべての新しい請求書にAddressInfo WHERE IsCurrent = 1を使用します
2
Dmitri Olechko

システムバージョン対応テンポラルテーブル(SQL Server 2016以降)を使用しないのはなぜですか。私はそれがあなたの要件に対処すると思います。

テンポラルテーブルをサポートする他のベンダーもあります。 OracleとIBM Db2の両方がこれを5〜6年間持っていましたが、SQL Serverの実装よりも間違いなく完全です。

また、ほとんどすべてのDBMSに独自のバージョンを実装することもできますが、一部が重複しているなど、他の部分より扱いにくい部分があります。パフォーマンスも少し難しいかもしれません。

1
Sameer

私はこの問題を抱えていた組織で働いていましたが、これが私たちがそれを解決した方法です。顧客とサービスの情報を含むデータベースが1つありました。顧客が変更を要求するたびに変更される住所フィールドがありました。

請求データベースは別個のエンティティであり、毎月の請求書にはその月に送信されたアドレスが含まれており、理論的には変更されることを聞いたことがありません。 100%確実ではありませんが、請求書アドレスはメインデータベースのテーブルの1つから毎月生成されたと思います。

納税義務があるため、請求書の住所の変更には注意が必要です。販売する製品や提供するサービスによっては、徴税率が郡ごとに異なる場合があり、監査を受け、将来この情報を提供する必要がある場合があります。過去の請求書の住所を変更すると、会社で問題が発生する可能性があります。

実際には2つ以上のデータベースがありましたが、その場合、請求書の作成プロセスは非常に複雑でした。請求書やその他の請求情報を保持する別のデータベースがあり、厳密に管理された請求書データを保持するテーブルがあり、SOX監査人は毎年それを確認していました。

あるデータベースには顧客サービスの使用状況データがそのままあり、別のデータベースには価格プランがあり、別のデータベースには顧客と製品のリスト/機能があり、毎月変更される税務情報用の別のデータベースがあり、徴収される税金は地域によって異なり、これらすべてがまとめられました。法案を作成します。一部の顧客は複数の場所を持っているため、税金は場所ごとに計算する必要があります。

同じサービスに対して異なる時期に購入され、異なる割引やセール価格が毎回適用されるため、一部の顧客は同じサービスに対して異なる価格を支払いました。一部の請求書は数ページであり、一部の顧客は数十ページから数百ページに請求書がありました。そして、支払い遅延などのためのさらにいくつかのデータベース。すべてが適切に説明され、請求されなければなりませんでした。

マスターの顧客名、番号、住所、製品などを含むメインデータベースがありました。これは通信会社であり、USOCSと呼ばれるものを持っています。これは、販売されたすべての製品のクレイジーコードです。医療請求コードに似ています。また、料金プラン用に個別のデータベースも用意しました。現在の携帯電話のプランと同じように考えてください。ただし、大規模な顧客もいれば、カスタムの商談もあるため、何千もの計画がありました。

非常に複雑だった理由の1つは、顧客にサービスを提供するエンドデバイスが生の使用状況データを持っているため、データベースにアップロードし、その顧客に請求される料金、場所、税率などに応じて価格を設定する必要があることです。在庫があり、誰にとっても同じ価格の物理的な製品とは異なります。

1
Alen

郵送先住所を使用して、請求書に結び付けないでください。その後、アドレスが変更されない場合は問題ありません。含まれている場合でも、特定の請求書が郵送された住所が残っています。

0
DCook