Normalization of Many to Many relation in sql

2019-04-13 13:30发布

问题:

I have a product table that contains two column

ProductID   Desc
  1         Fan
  2         Table
  3         Bulb

I have another table that contains supplier information

SupplierID    Desc
   1          ABC
   2          XYZ
   3          HJK

Now One supplier can supply multiple products and one product can be supplied by multiple suppliers To achieve this I have created another table tbl_Supplier_Product

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

Is it a good way to link this table to supplier and product table through primary composite key. In this table the primary key would be a composite key (SupplierID and ProductID) or should I add an extra column row ID for each record and then use that as a primary key and add a unique constraint to columns SupplierID and ProductID

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

What would the relationship of this table be to supplier table? I am a bit confused here because I added this table to resolve many to many relationship and redundant data but it still seems like this table has many to many relationship with both the tables??

回答1:

You don't need the extra column: a composite key is all you need

I would create a unique index that is the reverse of the PK too: this is useful for many queries and also provides an FK index for ProductID

After comment:

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

For more

  • SQL: Do you need an auto-incremental primary key for Many-Many tables? for more (see comments)
  • Difference between 2 indexes with columns defined in reverse order

And also use this generally to ensure that all your FKs have indexes

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

In an ERD (random one from a PowerPoint I have):