使用链接表将两个大的非规范化表拆分为多个表

时间:2014-03-12 16:45:19

标签: mysql sql sql-server database database-normalization

这是我的第一个stackoverflow问题,所以如果我没有问题礼仪,我很抱歉。

我有两个非常凌乱的大型桌子叫做中心和联系人 - 一个有公司和地址数据,另一个有联系人,公司和地址数据:

中心:
-CompanyGUID(PK)
-CompanyName
-MainTelephone
-MainEmail

〜ADDRESS1 〜ADDRESS2
-Town
- 邮编 注

联系人:
-ContactID(PK)
-FirstName
-LastName
-CompanyName
- 电话
- 电子邮件

〜ADDRESS1 〜ADDRESS2
-Town
-Postcode
-Notes

我正在尝试将此数据移动到一个新的规范化数据库中,该数据库具有单独的联系人,公司和地址表,并在每个表之间链接表以允许所有三个表之间的多对多关系:

公司
-CompanyGUID
-CompanyName
-MainTelephone
-MainEmail
-Notes

联系人:
-FirstName
-LastName
- 电话
- 电子邮件
-Notes

地址:

〜ADDRESS1 〜ADDRESS2
-Town
-Postcode

表格中有更多列,但这足以证明问题。许多公司和地址在两个表中都是相同的,但不一定。

我需要维护联系人,公司和地址之间的现有关系,同时删除冗余并允许公司和地址(companies_addresses链接表)和联系人和公司(companies_contacts链接表)之间的多对多关系。

我看过一些例子将一个表分成两个目标表,但我有三个,另外还有两个链接表。这可能吗?你会采取什么方法?

非常感谢任何可以提供帮助的人。

1 个答案:

答案 0 :(得分:1)

我认为您对五个表(公司,联系人,地址,公司地址,公司联系人)的建议很好。

我想知道你是否真的在地址和公司之间建立了多对多的关系。原始表中心仅为公司建议一个(主要?)地址。如果是这种情况,请跳过companies_addresses表并在表公司中添加外键。另一方面,在您的数据中,您可能具有多对多关系。

您可能希望保持联系人与其地址之间的关联。 (也许你不需要这个。我只是猜测。)在这种情况下,你需要在companies_addresses和contacts表之间有一个链接表而不是companies_contacts表:联系人将与特定地址相关联一家公司。

希望这有帮助。

此解决方案的SQL将如下所示:

-- tables
-- Table addresses
CREATE TABLE addresses (
    addressId int  NOT NULL,
    address1 varchar(255)  NOT NULL,
    address2 varchar(255)  NOT NULL,
    town varchar(255)  NOT NULL,
    postcode varchar(255)  NOT NULL,
    CONSTRAINT addresses_pk PRIMARY KEY (addressId)
);

-- Table companies
CREATE TABLE companies (
    companyGUID int  NOT NULL,
    companyName varchar(255)  NOT NULL,
    CONSTRAINT companies_pk PRIMARY KEY (companyGUID)
);

-- Table companies_addresses
CREATE TABLE companies_addresses (
    companies_companyGUID int  NOT NULL,
    addresses_addressId int  NOT NULL,
    CONSTRAINT companies_addresses_pk PRIMARY KEY (companies_companyGUID,addresses_addressId)
);

-- Table contacts
CREATE TABLE contacts (
    contactID int  NOT NULL,
    firstName varchar(255)  NOT NULL,
    lastName varchar(255)  NOT NULL,
    CONSTRAINT contacts_pk PRIMARY KEY (contactID)
);

-- Table contacts_companies_addresses
CREATE TABLE contacts_companies_addresses (
    contacts_contactID int  NOT NULL,
    companies_addresses_companies_companyGUID int  NOT NULL,
    companies_addresses_addresses_addressId int  NOT NULL,
    CONSTRAINT contacts_companies_addresses_pk PRIMARY KEY (contacts_contactID,companies_addresses_companies_companyGUID,companies_addresses_addresses_addressId)
);


-- foreign keys
-- Reference:  Table_5_contacts (table: contacts_companies_addresses)


ALTER TABLE contacts_companies_addresses ADD CONSTRAINT Table_5_contacts FOREIGN KEY Table_5_contacts (contacts_contactID)
    REFERENCES contacts (contactID);
-- Reference:  companies_addresses_addresses (table: companies_addresses)


ALTER TABLE companies_addresses ADD CONSTRAINT companies_addresses_addresses FOREIGN KEY companies_addresses_addresses (addresses_addressId)
    REFERENCES addresses (addressId);
-- Reference:  companies_addresses_companies (table: companies_addresses)


ALTER TABLE companies_addresses ADD CONSTRAINT companies_addresses_companies FOREIGN KEY companies_addresses_companies (companies_companyGUID)
    REFERENCES companies (companyGUID);
-- Reference:  contact_companies_addresses (table: contacts_companies_addresses)


ALTER TABLE contacts_companies_addresses ADD CONSTRAINT contact_companies_addresses FOREIGN KEY contact_companies_addresses (companies_addresses_companies_companyGUID,companies_addresses_addresses_addressId)
    REFERENCES companies_addresses (companies_companyGUID,addresses_addressId);