2016-07-03 138 views
1

我是设计数据库的新手,我不确定是否在我的应用程序的数据库设计中正确实现了规范化和关系。关系数据库设计 - 规范化和关系

该应用设计的购物清单和产品工程,并按如下要使用的数据库:

  • 用户通过Facebook登录到该网站。
  • 有一个大型的数百万“产品代码”表。每个产品代码代表不同的产品(例如Apple,TV,手机,牙刷等)。
  • 用户可以创建各种购物清单,每个购物清单将包含一个或多个“产品代码”。

我已经“尝试”在试图推断出一个可能的情况下更好地为数据库创建两种不同的设计。一个利用一对多的关系,以及一个多到多的关系,这两个链路和shopping_list产品的:

enter image description here

问题:

  1. 关于一对多:鉴于会有数百万个不同的产品ID,是不是一对多设计产生大量冗余信息在assigned_products表中?该产品表将具有相似的领域:

    ________________________________________________ 
    |assigned_p_id | shopping_list_id | product_code | 
    |--------------+------------------+--------------| 
    |  1  |  1   | aa11aab | 
    |--------------+------------------+--------------| 
    |  2  |  1   | zz1bbbb | 
    |--------------+------------------+--------------| 
    |  3  |  2   | aa11aab | 
    

,你可以看到,aa11aab重复两次因为别人创建购物清单,相同的项目,所以我不知道这种冗余会造成数据库问题每个重复的product_code会占用多少空间?

  • 关于多对许多:该图似乎是由具有表shopping_list_products商店ID值,而不是重复PRODUCT_CODE,然而,可以带走冗余,将这在检索信息时会导致性能损失?我假设几个加入将不得不在表格之间进行,以便每个单独的用户获得他们的所有购物清单和该购物清单内的产品代码。

  • 一般来说:我的关系/规范化可能有任何错误吗? (我是这方面的新手)

  • +0

    因此,您的第二个图解决了问题,因为产品对用户应该是不可知的,并且使用shopping_list和产品之间的桥接关系是完全没问题的。没有桥表的购物清单和产品永远不会相互认识。 – dmitryro

    +0

    Shopping_list_products也需要一个包。就目前而言,它应该是两个fks。你可能也需要一个数量。 – LoztInSpace

    +0

    @LoztInSpace我在设计数据库方面有点新鲜:),那么“Shopping_list_products”会包含它自己自动递增的ID(这可能是主键)。同时重写“两个fks”,你的意思是我会在该表中有两个外键?我甚至不确定这是否可行(由MySQL服务器允许) – Webeng

    回答

    0

    这里有一些关于从哪里开始的建议。

    您需要一张表来存储关于购买的信息。在数据中你可以看到威尔E狼已经购买了Dyno-might和钢琴......

    CREATE TABLE IF NOT EXISTS `purchase` (
        `id`   int unsigned  NOT NULL AUTO_INCREMENT, 
        `user_id`  int unsigned  NOT NULL, 
        `item_id`  int unsigned  NOT NULL, 
        `quantity`  double   DEFAULT 1, 
        `price`  double   NOT NULL, 
        `qwhen`  datetime   NOT NULL, 
        PRIMARY KEY (`id`), 
        FOREIGN KEY (`user_id`) REFERENCES user(id) ON DELETE RESTRICT ON UPDATE CASCADE, 
        FOREIGN KEY (`product_id`) REFERENCES product(id) ON DELETE RESTRICT ON UPDATE CASCADE 
    ) ENGINE=InnoDB Comment='Purchases'; 
    
    purchase data 
    +----+---------+------------+----------+--------+---------------------+ 
    | id | user_id | product_id | quantity | price | created    | 
    +----+---------+------------+----------+--------+---------------------+ 
    | 1 |  1 |   1 |  1 | 100.00 | 2016-07-02 20:42:13 | 
    | 1 |  1 |   3 |  1 | 734.23 | 2016-07-02 21:23:40 | 
    | .. | ....... | .......... | ........ | ...... | ................... | 
    +----+---------+------------+----------+--------+---------------------+ 
    

    您还需要一张表来存储产品信息。我假设您销售的是实物产品,因此我添加了eanupca和其他一些可能有用的列。

    CREATE TABLE IF NOT EXISTS `product` (
        `id`     int unsigned  NOT NULL AUTO_INCREMENT, 
        `manufacturer_id` int unsigned  NOT NULL, 
        `ean`    int unsigned  NOT NULL, 
        `upca`    int unsigned  NOT NULL, 
        `upce`    int unsigned  NOT NULL, 
        `name`    varchar(100)  NOT NULL, 
        `height`    double   DEFAULT NULL, 
        `width`    double   DEFAULT NULL, 
        `depth`    double   DEFAULT NULL, 
        `weight`    double   DEFAULT NULL, 
        PRIMARY KEY (`id`), 
        FOREIGN KEY (`manufacturer_id`) REFERENCES manufacturer(id) ON DELETE RESTRICT ON UPDATE CASCADE 
    ) ENGINE=InnoDB Comment='Item master file'; 
    
    product data 
    +----+-----------------+---------------+--------------+--------+------------+--------+-------+-------+--------+ 
    | id | manufacturer_id | ean   | upca   | upce | name  | height | width | depth | weight | 
    +----+-----------------+---------------+--------------+--------+------------+--------+-------+-------+--------+ 
    | 1 |    1 | 123456789| 123456789012 | 123456 | Dyno-might | 12.0 | 1.0 | 1.0 | 0.5 | 
    | 2 |    1 | 23456789| 23456789| 234567 | UltraLaser | 96.0 | 96.0 | 96.0 | 450.0 | 
    | 3 |    2 | 3456789| 3456789| 345678 | Piano  | 36.0 | 60.0 | 72.0 | 375.0 | 
    | .. | ............... | ............. | ............ | ...... | .......... | ...... | ..... | ..... | ...... | 
    +----+-----------------+---------------+--------------+--------+------------+--------+-------+-------+--------+ 
    

    当我们向人们推销物品时,很高兴正式解决这些问题,所以我们应该有一张有效的称呼表。 user表将具有该表的外键。

    CREATE TABLE IF NOT EXISTS `salutation` (
        `id`   varchar(5)  NOT NULL, 
        PRIMARY KEY (`id`) 
    ) ENGINE=InnoDB Comment='Salutations'; 
    
    salutation data 
    +------+ 
    | id | 
    +------+ 
    | Mr. | 
    | Mrs. | 
    | Miss | 
    | Ms. | 
    | Dr. | 
    | Rev. | 
    | .... | 
    +------+ 
    

    名称后缀是一个人的名字的一部分,所以我们将尽user表的一部分,并提供了一个外键到这个表。

    CREATE TABLE IF NOT EXISTS `suffix` (
        `id`   varchar(5)  NOT NULL, 
        PRIMARY KEY (`id`) 
    ) ENGINE=InnoDB Comment='Suffixes'; 
    
    suffix data 
    +-----+ 
    | id | 
    +-----+ 
    | Sr. | 
    | Jr. | 
    | II | 
    | III | 
    | IV | 
    | ... | 
    +-----+ 
    

    当然,我们有用户 - 尽管将它们称为客户可能更合适。

    CREATE TABLE IF NOT EXISTS `user` (
        `id`    int unsigned NOT NULL AUTO_INCREMENT, 
        `facebook_id`  int unsigned NOT NULL, 
        `email`   varchar(255) NOT NULL, 
        `salutation_id` varchar(5)  NOT NULL, 
        `first_name`  varchar(50) NOT NULL, 
        `middle_name`  varchar(50) DEFAULT NULL, 
        `last_name`  varchar(50) NOT NULL, 
        `suffix_id`  varchar(5)  DEFAULT NULL, 
        PRIMARY KEY (`id`), 
        FOREIGN KEY (`salutation_id`) REFERENCES salutation(id) ON DELETE RESTRICT ON UPDATE CASCADE, 
        FOREIGN KEY (`suffix_id`) REFERENCES suffix(id) ON DELETE RESTRICT ON UPDATE CASCADE 
    ) ENGINE=InnoDB Comment='Users'; 
    
    user data 
    +----+-------------+------------------------+---------------+------------+-------------+-----------+-----------+ 
    | id | facebook_id | email     | salutation_id | first_name | middle_name | last_name | suffix_id | 
    +----+-------------+------------------------+---------------+------------+-------------+-----------+-----------+ 
    | 1 | 123456789 | [email protected] | Mr.   | Wile  | E   | Coyote | NULL  | 
    | .. | ........... | ...................... | ............. | .......... | ........... | ......... | ......... | 
    +----+-------------+------------------------+---------------+------------+-------------+-----------+-----------+ 
    
    0

    你基本上在两种情况下都做同样的事情。在第一种情况下,您将shopping_list_id映射到product_code,在第二种情况下,您将其映射到product_id。无论您使用product_code还是product_id,它们似乎都是代表product实体的外键。在这两种情况下,要到达产品行,您必须使用该字段加入products表。

    作为一般规则,您应该映射两个id列(第二个选项),以便在两种情况下使用整数主键完成连接。这不仅可以提高存储和索引的效率,还可以使这些连接速度更快。

    另外,作为注释之一,您应该将自动递增主键添加到shopping_list_products表中。

    请注意,对于命名约定,您可能需要考虑总是用id命名主键。例如,对于每个表而言,您将不需要0​​等等。