【问题标题】:many to many relationship in mysql have to be the foreign keys the primary keys from both tables connections tables?mysql中的多对多关系必须是两个表连接表中的外键主键?
【发布时间】:2022-01-21 10:28:05
【问题描述】:

假设我有一个订单表和项目表:

CREATE TABLE if not exists ORDERS (
    ORDERID INTEGER AUTO_INCREMENT,
    ORDERTYPE VARCHAR (20) NOT NULL,
    ShippedTime VARCHAR(40),
    ORDERDATE DATE,
    PRIMARY KEY (ORDERID),
);
CREATE TABLE if not exists ITEM(
    ITEMID INTEGER AUTO_INCREMENT,
    NAME VARCHAR (20) NOT NULL,
    PRICE INTEGER NOT NULL CHECK (PRICE > 0),
    PRIMARY KEY (ITEMID)
);

两个表之间的关系将是存在的:

CREATE TABLE if not exists EXISTOF (
  ORDERID INTEGER NOT NULL,
  ITEMID INTEGER NOT NULL,
  FOREIGN KEY (ORDERID) REFERENCES ORDERS(ORDERID)  ON DELETE CASCADE,
  FOREIGN KEY (ITEMID) REFERENCES ITEM(ITEMID)  ON DELETE CASCADE,
  PRIMARY KEY (ORDERID,ITEMID)
);

解释应该是每个订单有多个项目,每个项目属于多个订单。 如果我这样做,它将不起作用,因为 id 是主键,我不能为特定订单插入多个项目,也不能项目属于多个订单。 有没有人有任何建议如何做到这一点?

【问题讨论】:

  • PRIMARY KEY (ORDERID,ITEMID) 很好,如果一个订单只能包含许多项目中的一个 itemid,如果一个订单可以在一个订单中多次包含相同的 itemid,那么一个键(即不是主键或唯一键)将是合适的 - 在任何一种情况下,都必须在连接表之前创建订单(和项目)
  • 那么可以不让orderid和itemid不是existof表中的主键吗?正如我所知,在多对多关系中应该创建新表,其主键是两个 id 还是错误?
  • 这取决于你。您可以定义具有唯一联结表 ID 和具有订单 ID 和订单项 ID 的唯一索引的联结表,或者您可以创建具有订单 ID 和订单项 ID 的复合主键。无论哪种方式都有优点和缺点。我的偏好是每个表都有一个唯一的自动递增 ID,并且所有参考 ID 都被编入索引。

标签: mysql sql database-design


【解决方案1】:

使用外键 item_id 和 order_id 创建中间表 OrderItems。还有其他选择,但这是我发现打破多对多关系的最简单方法!

【讨论】:

    【解决方案2】:

    您的 Existof 表不够灵活。大多数订单处理系统处理这种情况的方式是在 Existof 表中添加一个列,我们可以称之为 Quantity。默认值为 1,但也可以输入其他数量。

    因此,如果给定的订单要订购 5 令纸,并且产品中的纸令为 5 令,那么 Existof 中该商品的条目将有 5 个。

    这假设所有 5 令都是可互换的,因此由相同的数据描述。如果一些纸令的颜色不同,那么它们应该是不同的产品。

    【讨论】:

    • 但是由于existof中的orderid是主键,不能重复,怎么让同一个订单有另外的产品(不仅仅是paper)?
    • existof 中的 orderid 不是主键。 oderid、itemid 的组合是主键。顺便说一句,你有主产品表吗?这叫ITEM吗?这是一个令人困惑的名字。
    【解决方案3】:

    “……必须是……”——不。 FOREIGN KEYs 绝不是“必需的”。

    FK 提供三样东西:

    • 动态检查是否存在匹配元素。这可用于对数据进行完整性检查,但不是强制性的。
    • INDEX 使上述检查显着加快。手动指定INDEX 也一样好。无论如何,PRIMARY KEY 是一个索引。
    • “级联删除等”。这是很少有架构使用甚至需要的选项。

    表之间的“关系”主要有 3 种类型:

    1:1 -- 但是为什么要麻烦有两张桌子呢?这些列可以简单地位于一个表中。 (也有例外。)

    1:many -- (这听起来像是“一个订单中的许多项目”??)这是通过在Items 表中简单地使用order_id 来实现的。 (并索引该列。)可选地,它可以是 FK。其他人称该表为OrderItems。它链接到Products 表。

    many:many -- 当你需要一个额外的表时(通常)正好有两列,即另外两个表的 id。 (例如,学生与班级)每一列都可以是一个 FK,但最佳索引是 PRIMARY KEY(a_id, b_id)INDEX(b_id, a_id)。 FK 会看到您已经有以 a_id 和 b_id 开头的索引,因此它不会创建额外的索引。没有“唯一的联结表 ID”;它比我在这里建议的 PK 效率低。 (更多讨论:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table

    回到您提出的设计。我建议“项目”意味着该产品的产品和数量以及当时收取的价格。因此它需要是 1:many。而那个“产品”就是你所想的。请更改表名,以免我感到困惑。

    现在,另一个问题...价格。价格是永远固定的吗?或者今天的订单价格会与昨天的不同?同样,商品和价格与 one 订单相关联。 Product 表上可能有一个 Price,它可能是“current_price”,在创建新订单时使用。

    ShippedTime VARCHAR(40) -- 或许应该是DATETIME

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多