この状況に最適なデータベース設計は何ですか?


8

私は自分の会社のビジネスアプリケーションの構築に取り組んでおり、特定の状況に最適なデータベース設計を選択するのに苦労しています。次のエンティティがあるとします。

承認

  • Id
  • 状態
  • ...

ApprovalComment

  • Id
  • ApprovalId
  • コメント

注文

  • Id
  • ...

請求書

  • Id
  • ...

明らかに、複数のタイプの承認と、承認を必要とする複数のオブジェクトが存在する可能性があります。テーブルを設計するための次のオプションのうち、最も適切なものは何ですか。

オプション1

null外部キーを持つ1つの承認テーブルがあります。

承認

  • ID PK
  • 状態
  • OrderId FK NULL
  • InvoiceId FK NULL

ApprovalComments

  • ID PK
  • ApprovalId FK
  • コメント

この場合、承認が必要なすべてのオブジェクトに列を追加する必要があります

オプション2

共通のフィールドを持つ親の承認テーブルと、承認が必要な各オブジェクトの子テーブルを用意します。

承認

  • ID PK
  • 状態

ApprovalComments

  • ID PK
  • ApprovalId FK
  • コメント

OrderApprovals

  • ApprovalId PK FK
  • OrderId FK

InvoiceApprovals

  • ApprovalId PK FK
  • InvoiceId FK

オプション3

各オブジェクトの承認テーブルがあります。

OrderApprovals

  • ID PK
  • OrderId FK
  • 状態

OrderApprovalComments

  • ID PK
  • OrderApprovalId FK
  • コメント

InvoiceApprovals

  • ID PK
  • InvoiceId FK
  • 状態

InvoiceApprovalComments

  • ID PK
  • InvoiceApprovalId FK
  • コメント

これらはすべて有効なソリューションであることはわかっていますが、将来、さまざまな種類の承認を追加するのに最適なソリューションを決定することはできません。何かご意見は?

回答:


10

私が使用する経験則では、コードの変更や将来的に計画できる新しい機能に対応するためにテーブルを変更する必要があるのは、データベースの設計が悪いことです。

つまり、オプション1のバリアントを使用します

Approvals
    Id PK
    ApprovalTypeID FK
    Status


ApprovalComments
    ID PK
    ApprovalId FK
    Comment

ApprovalTypes
    ID PK
    Name

承認が必要な新しいタイプのオブジェクトを追加する場合、列を追加するためにテーブルを変更する代わりに、ApprovalTypesに行を挿入するだけで済みます。


この状況では、特定の注文/請求書とのid関係はどこに行きますか?注文が「クレジット承認」を必要とすると、承認タイプはクレジットになりますが、注文(またはエンティティ)にどのようにリンクしますか?また、クレジット承認のみに固有の追加の列はどこに移動しますか?
user1384977

これは少し複雑になります。CreditApprovalDetailsテーブルを持つことができます。承認を注文にリンクする必要がある場合は、1:1でない限り、結合テーブルが必要になります。ただし、アプリケーションを完全に理解していないと、情報に基づいた提案を行うことができません。
2010年

2

それは、DBのカーディナリティ、および格納するものによって異なります。たとえば、approval_commentを一意のように作成し、approvalとapproval_commentの間に1-1の関係を作成することができるため、1つの追加テーブルの作成をスキップします... Iこのように見た:

Cardinality:
Approval N ---- 1 Approval_comment.
Approval 1 ----- N Order
Order N ----- 1 Invoice

ここに画像の説明を入力してください


1

最初の選択肢に投票します。アイテムに承認の必要条件を追加すると、それらのアイテムの動作が適切に変更されるため、列の追加は大きな問題ではありません。また、クエリで結合を使用するのに最適な方法です。

2番目には不要な追加テーブルがあり、複数の承認が1つのアイテムに属する可能性があることを示唆している可能性があります。

3番目には、冗長なテーブルが多数含まれており、おそらくそれらを処理するための冗長なコードが含まれています。


1

3つのオプションのいずれかを決定する必要がある場合は、オプション2が最適だと思います。@sreimerは正解です。予測可能なイベントのためにテーブル構造を変更する必要があることは、設計が悪いことを示しています。OrderIDとInvoiceIDがApprovalsテーブルにあることは、私が見ているように、列全体の繰り返しグループに非常に近く、文字ではないにしても、最初の通常形式の精神に違反しています。

承認が必要な各テーブルにApprovalID列を追加することを検討します。値がnullの場合、承認されていません。それが選択肢でなければ、@ sreimerは適切な設計に基づいていると思います。


1

テーブルは1つだけにすることをお勧めします=>

承認

id

状態

コメント

そして、承認IDをinoviceまたはOrderテーブルに格納します。この方法では、オブジェクトごとに列を追加する必要がなく、維持するテーブルが少なくなります。そして、私が提供したオプションのどちらかを選択する必要がある場合は、オプション2を使用して、承認コメントを承認テーブルにマージします。


0

あなたはこのようなものを試すことができます:

承認
---------
  ID
  状態
  approver_name
  (他のもの)

注文
------
  ID
  (他のもの)

請求書
--------
  ID
  (他のもの)

承認されたオブジェクト
----------------
  ID
  Approval_id(FK-承認テーブルを参照)
  authorized_object_id(FK-請求書、注文などのIDを参照できます...)
  承認されたオブジェクトのタイプID(FKは承認されたオブジェクトのタイプを指します)

承認されたオブジェクトのタイプ
---------------------
  ID
  名前

このapproved_objects表は、どの承認がどの承認済みオブジェクトに適用されるかを示しています。承認されたオブジェクトがで可能性がありinvoicesordersそうでない、または何か。に基づいて、検索するテーブルを決定しますapproved_object_type_id。これは柔軟ですが、レポートを少しトリッキーにする可能性があります。

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