【问题标题】:Normalization of Many to Many relation in sqlsql中多对多关系的规范化
【发布时间】:2013-04-19 02:09:52
【问题描述】:

我有一个包含两列的产品表

ProductID   Desc
  1         Fan
  2         Table
  3         Bulb

我有另一个包含供应商信息的表

SupplierID    Desc
   1          ABC
   2          XYZ
   3          HJK

现在一个供应商可以提供多种产品,一个产品可以由多个供应商提供为了实现这一点,我创建了另一个表 tbl_Supplier_Product

 SupplierID    ProductID 
     1            1
     1            2
     2            1
     2            2
     2            3

通过主复合键将此表链接到供应商和产品表是否是一种好方法。在此表中,主键将是复合键(SupplierID 和 ProductID),或者我应该为每条记录添加一个额外的列行 ID,然后将其用作主键并向列 SupplierID 和 ProductID 添加唯一约束

 SupplierID    ProductID    Row ID
         1            1       1
         1            2       2
         2            1       3
         2            2       4
         2            3       5
UNIQUE CONSTRAINT(SupplierID, ProductID)

此表与供应商表的关系是什么?我在这里有点困惑,因为我添加了这个表来解决多对多关系和冗余数据,但看起来这个表仍然与两个表都有多对多关系??

【问题讨论】:

    标签: sql normalization database-normalization


    【解决方案1】:

    您不需要额外的列:您只需要一个复合键

    我也会创建一个与 PK 相反的唯一索引:这对许多查询很有用,并且还为 ProductID 提供了一个 FK 索引

    评论后:

    CREATE TABLE SupplierProduct (
        SupplierID int NOT NULL,
        ProductID int NOT NULL,
    
        PRIMARY KEY (SupplierID, ProductID)
    );
    GO
    CREATE UNIQUE NONCLUSTERED INDEX IXU_ReversePK ON SupplierProduct (ProductID, SupplierID);
    GO
    

    了解更多

    并且通常也使用它来确保您的所有 FK 都有索引

    SELECT  fk.name AS [Missing FK Index]
    FROM    sys.foreign_keys fk
    WHERE   EXISTS
            (
            SELECT  *
            FROM    sys.foreign_key_columns fkc
            WHERE   fkc.constraint_object_id = fk.object_id
                    AND NOT EXISTS
                    (
                    SELECT  *
                    FROM    sys.index_columns ic
                    WHERE   ic.object_id = fkc.parent_object_id
                            AND ic.column_id = fkc.parent_column_id
                            AND ic.index_column_id = fkc.constraint_column_id
                    )
            );
    GO
    

    在 ERD 中(我有一个 PowerPoint 中的随机一个):

    【讨论】:

    • 您能否详细说明“将创建一个唯一索引,该索引也是 PK 的反向:这对于许多查询很有用,并且还为 ProductID 提供 FK 索引”
    • 感谢您的解释,但如果显示在 ER 图中,此表与供应商和产品表的关系是什么。我认为这将是多对多。
    • 最后一件事,从这个页面 stackoverflow.com/questions/13499096/… 如果你看一下答案,它会说“如果你有一个复合主键,那么所有引用它的外键必须使用复合主键”是否意味着我必须将 productID 添加到供应商表和 SupplierId 到产品表。
    • 不是你的情况。 @marc_s 指的是一个简单的子表,它指的是单亲,单亲有一个复合键。它不像你的桌子那样是多对多的情况。
    【解决方案2】:

    您可以使用复合键,但现在使用代理键更为传统。代理项是一个主键,通常是唯一的 GUID,除了唯一标识表行的目的外,对任何人都没有任何意义。代理仅由软件在内部使用,因此通常用户永远不会看到它,也不需要看到它。

    您还应该使用主键的命名约定,其中 id 是主键(这应该是代理键)并且所有外键都是 table.id。表部分告诉您它是该表的外键。所以:

    product-supplier 表是一些人所说的“链接表”或“连接表”。规范化多对多关系是他们的职责。它将多对多的关系变成了一对多的关系,从此我们都过着幸福的生活。如此多的产品可以有许多供应商,并且许多供应商可以有许多产品由产品-供应商连接表标准化(解决),其中产品具有一对多的产品-供应商行,而供应商具有一对多的产品-供应商行。

    请注意,连接表可以称为供应商-产品或产品-供应商,无论以哪种方式命名,只要它以父表命名,中间有连字符即可,这也是一种命名约定.

    这里的重点是,您总是通过将多对多关系规范化为两个一对多关系来解决多对多关系,如此处所示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-18
      • 2013-01-22
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 2015-10-28
      相关资源
      最近更新 更多