正規化されたデータベースの詳細テーブルで孤立したレコードを防ぐにはどうすればよいですか?
-
19-08-2019 - |
質問
適切に正規化されていない古いデータベースを保守する必要があります。たとえば、注文から納品日までのプロジェクトのさまざまなマイルストーンに応じて、5 つ以上の異なる日付列が含まれるように成長した (またはマッシュルーム化した) プロジェクト テーブルがあるとします。また、住所、メール アドレス、または Web リンクの列をそれぞれ含むいくつかのテーブルもあります。
構造を正規化し、住所や予定日などのテーブルを作成し、1:Nの関係(顧客ごとの住所、プロジェクトごとの納期など)を可能にするために必要なテーブルを作成したいと考えています。
現時点では、詳細テーブルのデータへの変更をどのように処理するかがまったくわかりません。たとえば、顧客の配送先住所が変更された場合を考えてみましょう。複数のレコード (おそらく複数のテーブル) がそのレコードを参照する可能性があるため、アドレス テーブル内のデータを変更することは問題外です。新しい住所レコードを追加すると、他の行に外部キー関係がない場合、古いレコードが孤立したままになる可能性があります。
これに対処するために次の方法を考えました。
新しいディテール レコードを追加し、古いディテール レコードを削除する必要があるかどうかをマスター テーブルの更新トリガーでチェックインします。これには、詳細テーブルとの関係を持つすべてのテーブル (すべてのテーブルまたは sproc) に関する知識が必要になります。私はこの別れの喪失が好きではありません。また、アクティブなトランザクションにさらに多くのテーブルが含まれることになります。
トリガーで古い詳細レコードの削除を試行し、エラーをキャッチします。これは間違っていると感じます。
孤立したレコードをそのまま使用し、定期的なメンテナンス タスクですべての詳細テーブルをクリーンアップします。
複数のマスターテーブルにリンクされている詳細テーブルのデータ変更を処理するための推奨される方法は何ですか?これを読むためのヒントはありますか?
解決
問題の一部は、元のスキーマ設計である可能性があります。外部キーが間違った方向を指し、住所や電話番号などを詳細ではなくマスターとして扱います。これは、特定のアドレスのすべての使用を一度に更新したい場合に便利かもしれませんが、私の経験では、それは常に非常に多くの困難な例外的なケースに移ります。既存のレコードを更新するために世帯またはオフィスが移動します。 CRUD画面でユーザーからこの詳細を非表示にしようとすると、目的の処理が実行されない状況に陥ります。
重複する値を折りたたむためにそのようにした場合、データベースの非正規化になります。アドレス行が存在するだけでは意味がありません。唯一の違いは、ほとんどの非正規化とは異なり、速度ではなくスペースの効率化を試みることです。その時点でリンクテーブルを作成することは、単に問題を悪化させるだけです。
たとえば、連絡先ごとに複数の住所が必要な場合は、親連絡先を指す外部キーを持つ住所を詳細テーブルに作成します。これらは単なる値であるため、重複した住所の値を心配する必要はありません。それ以外の場合は、Addressを実際のエンティティにします。タイトルまたは説明フィールドとCRUD画面を追加して、エンティティとして独立できるようにします。
他のヒント
孤立したレコードでライブを行い、定期的なメンテナンスタスクですべての詳細テーブルをクリーンアップします。
削除と更新のケースを曖昧にしていると思います。
クライアント a とクライアント b があり、両方が同じアドレスを使用している場合、それはリレーショナル テーブル (ClientAddresses など) のレコードに反映されます。ただし、複数のエンティティのアドレスを格納している場合は、より複雑になると思います。それ)
2 つのクライアントがアドレスを共有し、それがクライアント a にとって正しくない場合、クライアント b にとっても正しくない (つまり、データ入力エラー) と思いますが、クライアント a に変更を加えたくないことが確実な場合は、ベース アドレス情報を削除し、関連付けレコードを削除 (ClientAddresses から削除) し、新しいアドレスを追加します。リレーショナル テーブル (おそらくストアド プロシージャから) から削除を実行するときは、関連付けが解除されているアドレス レコードを参照している他のレコードがあるかどうかを確認し、そうでない場合はベース テーブルから削除します。