次の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
列には何を格納しますか?
いくつかのオプションがあります。私が最も好きなものについて説明しますが、「データベースでの多形関連の解決」を検索している他の人を見つけることができます。 companies
とcontacts
の共通テーブルを追加します(contacts
をpeople
またはpersons
に名前変更したい)。たとえば、party
と言います。したがって、companies
およびcontacts
はparty
への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));