3

これは非常に基本的なデータベース設計/正規化の質問です。

Books次の列を持つテーブルがあるとします。

isbn|title|author|status

、、、のstatusいずれかになりますchecked out(整数として格納されます)。availableoverduelost

行を追加するときに、「実際には、ステータスがのときに、checked out別のフィールドを保存したい」と判断しますdue_dateこのフィールドは、ステータスがチェックアウトされている書籍にのみ保存します。それ以外の意味はありません。

これを行うための標準的で正しい、標準的な方法は何ですか?

1つのアプローチは、列を追加しNULLてステータスがそうでない場合に設定することですchecked outが、これは私には悪い考えのように聞こえます(特に、ステータスがavailableあり、ステータスがある場合はどうなりますdue_dateか?)

もう1つの明白な答えは、テーブルを作成してペアDueDatesを格納することです。これは私が通常採用しているアプローチですが、テーブルやsがいたるところにあるisbn|due_dateことになりがちです。JOIN

私は本を​​具体的に保管する方法を探していません。それは問題の単なる例であり、標準的な解決策を知りたいです。

編集:ステータスのみ(、、、、 ...)のフィールドをたくさん追加し、ステータスがそうでないかのようにこれらすべてを追加したい場合、答えは変わりますか?checked outdue_dateborrowed_bychecked_out_fromNULLchecked out

4

6 に答える 6

3

これらの場合に使用するアプローチは、オプションの列とチェック制約を追加して、別の列に特定の値がある場合は列がいっぱい(つまりnullではない)であり、他の列が空の場合(つまりnull)であることを確認することです。列には他の値があります。

あなたの場合、制約は次のように書くことができます

CHECK ((due_date IS NOT NULL) = (status = 'CHECKED OUT'))

複数の列をチェックする必要がある場合は、列ごとに1つずつ複数の制約を追加するか、有効なすべての組み合わせをリストしてそれらを1つのチェック制約に結合します。

CHECK (status = 'A' AND due_date IS NULL OR status = 'B' AND due_date is NULL
OR status = 'C' AND due_date IS NOT NULL OR status = 'D' AND due_date IS NOT NULL)

NB ANDはORよりも優先順位が高いため、この場合は角かっこは必要ありませんが、わかりやすくするために角かっこを追加することをお勧めします。

チェック制約が別のテーブルをクエリしない可能性があるため、ほとんどのDBMS製品では不可能ではないにしても、別のテーブルを追加すると、これがより困難になります。

于 2012-10-02T08:22:06.657 に答える
3

あなたが述べたように、問題は基本的にタイピングとサブタイピングの1つです。「チェックアウトされた本」は一種の本です。「利用可能な本」は別の種類の本です。本は時間の経過とともに状態から状態へと進行する可能性があり、したがって時間の経過とともに1つのサブタイプまたは別のサブタイプに属する可能性があります。

オブジェクトモデリングでは、この種の問題はクラス、サブクラス、および継承を通じて処理されます。

ERモデリングでは、この種の問題は「特殊化」と呼ばれます。ERの専門分野を扱った記事をWebで見つけることができます。時間とともに変化する専門分野を扱った例を見たことがありません。ペットの場合のように、例の多くは時間の変化です。

リレーショナルモデリングとリレーショナルデータベースの設計では、特殊化を実装するためのテーブルを構築するためのいくつかの標準的な方法があります。

最初の標準的な方法は「単一テーブル継承」と呼ばれます。これは基本的にあなたが設計したものです。特定の行のサブタイプに関係しないデータには、多くのNULLが発生します。ただし、結合を行う必要はありません。

2番目の標準的な方法は、「クラステーブル継承」と呼ばれます。このように、クラスとサブクラスごとに個別のテーブルがあり、それらには共有主キーがあります。SOおよびWebで、「クラステーブル継承」と「共有主キー」の両方を検索できます。より多くの参加を行いますが、NULLは少なくなります。

他の方法があります。

どちらの方法が最適かは、手元のケースによって異なります。

于 2012-10-05T10:15:46.273 に答える
1

厳密に正規化されたデータ構造が必要な場合は、期日テーブルの使用がより正規化されます。

ステータスに依存する期日を持つことは多値従属性であり、したがって第4正規形の違反です。

これは、ステータスが「checked_out」とdue_dateであるという問題を回避するものではありません。ステータスが使用可能な場合は、duedateフィールドにエントリを設定するのと同じように、duedatesテーブルにエントリを設定することもできます。

(余談ですが、このライブラリの例では、本の「紛失」ステータスからローンを分離します)

于 2012-10-02T08:15:54.240 に答える
1

冗長データの削除は、同期を維持するためにチェックを強制するよりも優れています

最初の例での実際の問題は、ステータス列が他の場所に保持されている情報を複製しており、due_dateによって詳細に保持されていることです。

具体的には、ステータス「On Loan」、「Available」、「Overdue」はすべてdue_dateに基づいているため、データの同期を強制しようとしています。同期する必要のある重複データを保存しないように、システムを簡素化することをお勧めします。

コメントに示されている2番目の例では、Colinの答えが正しい方法だと思いますが、これらの制約の例を減らすためにデータベースを設計するよりも、常に2番目の選択肢になります。

于 2012-10-02T08:48:21.943 に答える
1

それでもベーステーブルに列を追加し、ステータスの値がに等しくないときにがNULLにCHECK CONSTRAINTなるようにaを定義します。DueDateCHECKED OUT

ISBNを正規化して別のテーブルに保存する->別のテーブルでの期日マッピングには、ステータスがチェックアウトされていないISBNがそのテーブルに含まれないようにするためのアプリケーション層コードが必要です。

于 2012-10-02T08:17:57.310 に答える
0

問題は初期モデル(定義)にあるようです。物理的な本(メディア上の本)と一般的な本には違いがあり{ISBN, Title, Author}ます。例のテーブルを見ると、依存関係がありますが、FD{ISBN} --> {Title, Author}{ {Status}ISBN}に依存していないため、ステータスはこのテーブルに属していません。

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

基本的に、ステータスは派生属性です

select
      c.ISBN
    , b.BookTitle
    , c.BookCopyNo
    , case
      when  ReturnDate is not null                              then 'available'
      when (ReturnDate is null) and (current_date < DueDate)    then 'checked out'
      when (ReturnDate is null) and ((current_date - DueDate) >= 100 ) then 'lost'
      when (ReturnDate is null) and (current_date > DueDate)    then 'overdue'   
      end as BookStatus

from CheckOut as c
join Book     as b on b.ISBN = c.ISBN
where c.CheckOutDate = (select max(xx.CheckOutDate)
                          from CheckOut as xx
                         where xx.ISBN       = c.ISBN
                           and xx.BookCopyNo = c.BookCopyNo)
;
于 2012-10-02T16:39:37.093 に答える