数据库设计 - 不同表格的多个“联系信息”

11

我有一个包含"person"、"company"、"shop"等表的数据库。这些表中很多都需要有"联系信息"。在数据库设计 - 多个实体的相似联系信息中要求设计这一功能。

现在,在我的数据库中,每个联系数据都可以拥有多个地址、电话和电子邮件。这是我的数据库模式:

database contact information

所以,我创建了一个中间表"contact",作为将"联系信息"链接到每个表的最简单方法。
我的问题是:这样做并且拥有只有一行的表是一个好的实践吗?


1
只有一行还是只有一列? - Stephen R
3个回答

8
这是我设计你的数据库的方式:
address_types
    id              unsigned int(P)
    description     varchar(10) // Mailing, Physical, etc.

addresses
    id              unsigned int(P)
    line1           varchar(50) // 123 Main Street, etc.
    line2           varchar(50) // Default NULL
    city_id         unsigned int(F cities.id)
    zip             varchar(6) // 12345, A1A 1A1, etc.
    zip4            char(4) // Default NULL
    lat             decimal(10,8) // 13.12345678, etc.
    lon             decimal(11,8) // 110.12345678, etc.

cities
    id              unsigned int(P)
    state_id        unsigned int(F states.id)
    name            varchar(50) // Omaha, Detroit, Tampa, etc.

companies
    id              unsigned int(P)
    name            varchar(75) // IBM, Microsoft, RedHat, etc.
    ...

companies_addresses
    id                  unsigned int(P)
    company_id          unsigned int(F companies.id)
    address_id          unsigned int(F addresses.id)
    address_type_id     unsigned int(F address_types.id)

companies_contacts
    id                  unsigned int(P)
    company_id          unsigned int(F companies.id)
    contact_id          unsigned int(F contacts.id)
    contact_type_id     unsigned int(F contact_types.id)

companies_emails
    id                  unsigned int(P)
    company_id          unsigned int(F companies.id)
    email_id            unsigned int(F emails.id)
    email_type_id       unsigned int(F email_types.id)

contact_types
    id              unsigned int(P)
    description     varchar(10) // Home phone, Mobile phone, FAX, etc.

在北美,电话号码的格式为:CC-AAA-EEE-SSSS-XXXXXXX,其中CC代表国家代码,AAA代表区号,EEE代表交换机号,SSSS代表站点号,XXXXXX代表分机号。

contacts
    id              unsigned int(P)
    country_code    varchar(3)
    area_code       varchar(3)
    exchange        varchar(3)
    station         varchar(4)
    extension       varchar(10) // Default NULL

请查看 ISO 3166-1

countries
    id              char(2) // ca, mx, us, etc.
    iso3            char(3) // can, mex, usa, etc.
    iso_num         char(3)
    name            varchar(44) // Canada, Mexico, United States, etc.

email_types
    id              unsigned int(P)
    description     varchar(10) // Personal, Work, etc.

emails
    id              unsigned int(P)
    address         varchar(255) // support@ibm.com, etc.

shops
    id              unsigned int(P)
    name            varchar(45) // Shop A, Shop B, etc.
    ...

shops_addresses
    id                  unsigned int(P)
    shop_id             unsigned int(F shops.id)
    address_id          unsigned int(F addresses.id)
    address_type_id     unsigned int(F address_types.id)

shops_contacts
    id                  unsigned int(P)
    shop_id             unsigned int(F shops.id)
    contact_id          unsigned int(F contacts.id)
    contact_type_id     unsigned int(F contact_types.id)

shops_emails
    id                      unsigned int(P)
    shop_id                 unsigned int(F shops.id)
    email_id                unsigned int(F emails.id)
    email_type_id           unsigned int(F email_types.id)

请查看ISO 3166-2
states
    id              unsigned int(P)
    country_id      char(2)(F countries.id)
    code            varchar(2) // AL, NF, NL, etc.
    name            varchar(50) // Alabama, Newfoundland, Nuevo León, etc.

好的,我理解你的观点了。你提出的解决方案与这里 https://dev59.com/sVDTa4cB1Zd3GeqPHTzu (方法1) 相同。但是这里也有一个同样的缺点 - "创建了许多联合表"。还有其他的方法吗? - nb.ag
2
这并不是一个劣势,规范化是一件好事。只要正确地索引事物,关系型数据库在连接表方面非常出色。 - Benny Hill
我知道这个已经有两年了,但是我想知道你对于在每个XXXX_emails表上放置email_type_id而不是放在email表上的想法是什么,因为每封电子邮件都会有一个类型。我正在设计类似的东西,并且得出了与你类似的设计(除了没有将电话号码拆分成那么多列),只是我打算将email_type_id放在电子邮件表上。 - kralco626
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Benny Hill

3
我的问题是:这样做并拥有只有一行的表是否是一个好的实践?
不完全是。从您的图表中可以看出,我必须问:联系人是否真的可以链接到任意数量的人?如果不是,您应该使用“人员”作为您的父表,并使其他表链接到它。

实际上,我可以有一千个人、公司和商店。如果我理解你的建议正确的话,我需要直接将电子邮件、电话和地址链接到所有实体(人员、公司、商店)?那么我会得到类似这样的东西: email -> idemail, mail, idperson, idcompany, idshop 这真的更好吗? - nb.ag
1
不,根据Benny Hill的建议,在你的情况下,你应该使用关联表。虽然也有其他方法,但是确保数据保持一致将会非常麻烦且得不偿失。 - AurelienT
也将国家链接到地址而不是城市,因为可能会有同名的城市位于不同的国家和/或州/省/县。 - AquaAlex

2

个人而言,我不太喜欢这种方法,因为我们需要为每个表创建一个实体和大量的联结表。我建议使用一张表来存储联系信息,另一张表来存储地址。

informations
- id INT
- name VARCHAR
- value VARCHAR
- type ENUM(phone, email, url, custom)
- idcompany INT NULL
- idcontact INT NULL

并且
addresses
- id
- address1
- address2
- district
- postcode
- idcity
- idcompany
- idcontact

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接