「customers」、「companys」、「phone_numbers」という 3 つのテーブルがあるとします。顧客と企業の両方が複数の電話番号を持つことができます。phone_numbers をインデックス化する最良の方法は何ですか? customer_id と company_id の両方を持ち、そのうちの 1 つを null のままにしますか? phone_numbers と 1 対多の関係を持つテーブルが 3 つ以上ある場合はどうなりますか?
4 に答える
ビジネス ルールでは 1 対多しか規定されていないかもしれませんが、実際には、人と企業は多対多の関係になる可能性があります。1 人が複数の電話番号 (自宅、携帯電話など) を持つことができ、1 つの電話番号が多くの人 (自分自身、大切な人など) に関連付けることができます。同様に、会社の番号と私の会社の番号は同じでもかまいません。内線番号を使用して直接私に連絡してください。
外部キーにインデックスを付けることは良い考えですが、時期尚早の最適化に注意してください。設定によっては、電話番号列に一意の制約を検討しますが、電話番号列自体を主キーにすることはありません。
顧客テーブルと会社テーブルの ID 列を使用してから、電話番号テーブルであなたが言ったようにして、1 つを null にし、もう 1 つを入力します。私はこれに似たようなことをしていますが、両方の値がnullにならないようにデータを検証する限り、うまくいきます。より洗練されたソリューションでは、2 つの列を使用できます。1 つは ID で、もう 1 つは型識別子です。顧客の場合は 1、企業の場合は 2 とします。そうすれば、null データや多くの余分な列について心配する必要がなくなります。
phone_numbers テーブルに 2 つの列を追加します。1 つ目は、関連付けるテーブルを示すインデックスです (たとえば、1 = 顧客、2 = 会社)。2 番目は、適切なテーブルへの外部キーになります。
このようにして、必要な数の電話番号ソースを追加できます。
特定の個人または会社が複数の電話番号を持っている場合、phone_numbers テーブルには複数の行があります。
パターンに最も近いものは次のとおりです。多対多の関係を持つ 2 つのエンティティには、それらの間に関連エンティティ (相互参照テーブル) が必要です (代理キーを想定)。
CREATE TABLE CUSTOMER_XREF_PHONE
( CUSTOMER_ID NUMBER NOT NULL,
PHONE_NUMBER_ID NUMBER NOT NULL,
CONSTRAINT CUSTOMER_XREF_PHONE_PK
PRIMARY KEY (CUSTOMER_ID, PHONE_NUMBER_ID),
CONSTRAINT CUSTOMER_XREF_PHONE_UK
UNIQUE (PHONE_NUMBER_ID, CUSTOMER_ID),
CONSTRAINT CUSTOMER_XREF_PHONE_FK01
FOREIGN KEY (CUSTOMER_ID)
REFERENCES CUSTOMER (CUSTOMER_ID) ON DELETE CASCADE,
CONSTRAINT CUSTOMER_XREF_PHONE_FK02
FOREIGN_KEY (PHONE_NUMBER_ID)
REFERENCES PHONE_NUMBERS (PHONE_NUMBER_ID) ON DELETE CASCADE
);
このような実装パターンは次のことができます。
データベース レベルの参照整合性制約によって完全に保護される
双方向アクセスをサポートします(その電話番号を持っている他の人を確認する必要がある場合があります)
データベースがサポートしている場合はセルフクリーニング
ON DELETE CASCADE
「関係タイプ」属性を使用して拡張し、次のようなエンティティ間の複数の独立した関係をマッピングします。
- 顧客は自宅の電話番号を持っています
- 顧客は日中の電話番号を持っています
- 顧客はファックスの電話番号を持っています
- 顧客は携帯電話番号を持っています