【问题标题】:Database many-to-many intermediate tables: extra fields数据库多对多中间表:额外字段
【发布时间】:2011-06-27 14:34:12
【问题描述】:

我创建了一个“shops”和一个“customers”表以及一个中间表customers_shops。每个商店都有一个site_url 网址,除了一些客户使用备用网址来访问商店的网站(此网址对特定客户来说是唯一的)。

在下面的中间表中,我添加了一个附加字段shop_site_url。我的理解是这是第二规范化形式,因为the shop_site_url 字段对于特定客户和商店是唯一的(因此不会为不同的客户/商店重复)。此外,由于它取决于客户和商店,我认为这是第 3 种标准化形式。我只是不习惯使用“映射”表 (customers_shops) 来包含其他字段 - 下面的设计是否有意义,或者我应该保留中间表纯粹作为转换多对多一对一的关系?

######
customers
######

id INT(11) NOT NULL PRIMARY KEY
name VARCHAR(80) NOT NULL

######
shops
######

id INT(11) NOT NULL PRIMARY KEY
site_url TEXT

######
customers_shops
######

id INT(11) NOT NULL PRIMARY KEY
customer_id INT(11) NOT NULL
shop_id INT(11) NOT NULL
shop_site_url TEXT //added for a specific url for customer

谢谢

【问题讨论】:

    标签: mysql database database-design normalization join


    【解决方案1】:

    您所说的“中间”表不是特殊类型的表。桌子只有一种,设计原则应该适用于所有人。

    【讨论】:

      【解决方案2】:

      好吧,让我们创建表,插入一些示例数据,然后查看结果。

      id cust_id  shop_id  shop_site_url
      --
      1  1000     2000     NULL
      2  1000     2000     http://here-an-url.com
      3  1000     2000     http://there-an-url.com
      4  1000     2000     http://everywhere-an-url-url.com
      5  1001     2000     NULL
      6  1001     2000     http://here-an-url.com
      7  1001     2000     http://there-an-url.com
      8  1001     2000     http://everywhere-an-url-url.com
      

      嗯。 那个看起来不太好。让我们暂时忽略备用 URL。要创建解析 m:n 关系的表,您需要对构成 m:n 关系的列进行约束。

      create table customers_shops (
          customer_id integer not null references customers (customer_id),
          shop_id integer not null references shops (shop_id),
          primary key (customer_id, shop_id)
      );
      

      (我删除了“id”列,因为它往往会掩盖正在发生的事情。如果您愿意,可以稍后添加。)

      插入一些示例数据。 . .那么

      select customer_id as cust_id, shop_id
      from customers_shops;
      
      cust_id  shop_id
      --
      1000     2000
      1001     2000
      1000     2001
      1001     2001
      

      那就更近了。您应该在这种表格中为客户和商店的每个组合只保留一行。 (即使没有 url,这也是有用的数据。)现在我们如何处理替代 URL?这取决于几件事。

      • 客户是否通过 只有一个 URL,或者他们可能会使用更多 不止一个?

      如果答案是“只有一个”,那么您可以在此表中为 URL 添加一列,并使该列唯一。这是此表的候选键。

      如果答案是“不止一个——至少是站点 url 和替代 url”,那么您需要对约束做出更多决定,因为更改此表以允许每个客户和商店跨越了这一要求:

      shop_site_url 字段是唯一的 特定客户和商店 (因此不会重复 不同的客户/商店)

      本质上,我要求您确定此表的含义——定义表的谓词。例如,这两个不同的谓词导致不同的表结构。

      • 客户“n”访问了该网站 对于使用 url 's' 的商店'm'
      • 允许客户“n”访问 商店“m”的网站使用备用 网址's'

      【讨论】:

      • 确实 primary key (customer_id, shop_id) 在我的情况下有效,那么 url 是唯一的,即“只有一个”url。感谢您讨论该方法中的想法。
      【解决方案3】:

      您的架构确实有意义,因为shop_site_url 是关系本身的一个属性。您可能想给它一个更有意义的名称,以便将其与 shops.site_url 区分开来。

      【讨论】:

        【解决方案4】:

        您还会将这些信息放在哪里?这不是商店的属性,也不是客户的属性。你可以把它放在一个单独的表中,如果你想避免有一个 NULLable 列,但你最终不得不从这个新表中引用你的中间表,这可能看起来对你来说更奇怪。

        【讨论】:

          【解决方案5】:

          关系可以有属性,就像实体可以有属性一样。

          实体属性进入实体表中的列。至少对于多对多关系而言,关系属性位于关系表中。

          听起来好像一般来说,URL 是由商店和客户的组合决定的。所以我会把它放在 shop-customer 表中。许多商店只有一个 URL 的事实表明存在比这更微妙的第五范式。但是我懒得解决了。

          【讨论】:

          • “关系表”只是表示任何具有多个外键的表,不是吗?为什么我们需要为具有多个外键的表指定一个特殊名称?这是我从未想过的事情。
          猜你喜欢
          • 2017-07-02
          • 2016-12-17
          • 2018-12-25
          • 2019-08-10
          • 1970-01-01
          • 1970-01-01
          • 2015-06-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多