web-dev-qa-db-ja.com

複数のテーブルの外部キー

次の3つのテーブルがあります。

╔═════════════════╗
║   Companies     ║
╠═════════════════╣
║ id              ║
║ name            ║
║ type            ║
║ etc...          ║
╚═════════════════╝
╔══════════════╗
║   Contacts   ║
╠══════════════╣
║ id           ║
║ company_id   ║
║ first_name   ║
║ last_name    ║
║ etc...       ║
╚══════════════╝
╔═══════════════╗
║   Addresses   ║
╠═══════════════╣
║ id            ║
║ foreign_key   ║
║ address_1     ║
║ address_2     ║
║ city          ║
║ state         ║
║ Zip           ║
║ etc...        ║
╚═══════════════╝

私の問題は、会社と連絡先の両方に複数のアドレスを関連付けることができることです。 ID番号が重複している可能性があります。 addressesテーブルのforeign_key列には何を格納しますか?

4
MegaHit

いくつかのオプションがあります。私が最も好きなものについて説明しますが、「データベースでの多形関連の解決」を検索している他の人を見つけることができます。 companiescontactsの共通テーブルを追加します(contactspeopleまたはpersonsに名前変更したい)。たとえば、partyと言います。したがって、companiesおよびcontactspartyへのFKを持ちます。次に、リンクテーブルparty_address(address_id,party_id)をFKとともにaddressesおよびpartyにそれぞれ追加します。

[〜#〜] update [〜#〜]たとえば(あまりに単純化されていることはわかっていますが、通常は異なるaddress_type、アドレス変更履歴などがあるかもしれませんが、アイデアを示していると思います)。

注:mysqlにはまだチェック制約がないため、列挙型が使用されます。 (party_id、party_type)に一意の制約が追加されたため、子テーブルは外部キー参照を使用できます。したがって、データベースレベルで実装および適用されるオプションの関係-関係者は、個人または組織のいずれかです。人と組織が同時に存在することはできません。

  CREATE TABLE PARTY (party_id int not null auto_increment primary key,
party_type enum('person','organization') not null,
CONSTRAINT UQ_PARTY UNIQUE(party_id,party_type));

CREATE TABLE PERSON (party_id int not null primary key, 
party_type enum('person') NOT NULL DEFAULT 'person',
....
CONSTRAINT FK_PERSON_PARTY FOREIGN KEY(party_id,party_type) 
 REFERENCES PARTY(party_id,party_type));

CREATE TABLE ORGANIZATION (party_id int not null primary key, 
party_type enum('organization') NOT NULL DEFAULT 'organization',
....
CONSTRAINT FK_PERSON_PARTY FOREIGN KEY(party_id,party_type) 
 REFERENCES PARTY(party_id,party_type));

CREATE TABLE ADDRESS(address_id INT NOT NULL auto_increment PRIMARY KEY,
.... );

CREATE TABLE PARTY_ADDRESS (party_id INT NOT NULL, address_id INT NOT NULL,
CONSTRAINT PK_PARTY_ADDRESS PRIMARY KEY(party_id,address_id),
CONSTRAINT FK_PARTY_ADDRESS_PARTY FOREIGN KEY (party_id) REFERENCES PARTY(party_id),
CONSTRAINT FK_PARTY_ADDRESS_ADDRESS FOREIGN KEY (address_id) REFERENCES ADDRESS(address_id));
4
a1ex07