MySQL表设计和规范化帮助

JM4*_*JM4 6 mysql database-design normalization

注意:这个问题已于11/19/12重新定义,以供澄清.我通常在这里没有太多问题,但努力为客户端站点设计新的产品系统.我们提供一套产品,每个客户都可以向他的客户销售.我们可能会随时添加新产品,但它们都遵循以下格式:

  1. 类别
  2. 类型
  3. 产品

使用之前的结构给出一个真实世界的例子:

  • 棒球设备
    • 手套
      • 罗林斯
      • 耐克
      • Mizzuno
    • 蝙蝠
      • 伊斯顿
      • Louisville Slugger
  • 足球装备
      • 耐克
      • 锐步
      • 阿迪达斯
    • 橄榄球
      • 耐克
      • Saplding
      • 威尔逊
  • ....

上面的列表显然仍在继续,可以更大,更大,但它提供了整体的想法.

目前,我正在存储特定客户可以在单个平面格式表中销售的产品类型,如下所示:

ID  | clientID | categoryID | typeID | productID | customURL
=============================================================
1   |  111     |    1       |   1    |   1       | 1111
2   |  111     |    1       |   2    |   2       | 2222
3   |  111     |    1       |   2    |   3       | 3333
4   |  111     |    2       |   3    |   4       | 4444
5   |  222     |    1       |   1    |   1       | 5555
6   |  222     |    2       |   3    |   4       | 6666
Run Code Online (Sandbox Code Playgroud)
  • 在上面的例子中,类别1可以是"棒球装备",类别2是"足球装备"
  • 相应的categoryID,typeID和productID的名称将存储在具有FK关系(innodb)的3个seaprate表中,以便维持规范化.
  • 类型指的是二级物品(手套,蝙蝠,鞋子,足球等).这些数字永远不会相交(意味着即使一般产品是相同的,也永远不会有相同的类型ID(棒球中的鞋子比足球鞋子的内容更多).
  • 在此表中,clientID 1可以销售4个产品,1个类别1个,类别2个1个.ClientID 2可以销售2个产品,每个类别一个.

我倾向于保持表格的结构,但在其他设计中我知道我可能已将表格分开以进行标准化目的我不确定是否适用于此处.如果我将它们分解出来,我会看到这从一个表到4个或更多,如下所示:

productsOffered表

ID  | clientID | productID | customURL
======================================
1   |  111     | 1       | 1111
2   |  111     | 2       | 2222
3   |  111     | 3       | 3333
4   |  111     | 4       | 4444
5   |  222     | 1       | 5555
6   |  222     | 4       | 6666
Run Code Online (Sandbox Code Playgroud)

productsDefinition表

ID  | productID | typeID | productName
======================================
1   |  1        |    1   | rawlings glove
2   |  2        |    2   | product2
3   |  3        |    2   | product3
4   |  4        |    3   | product4
Run Code Online (Sandbox Code Playgroud)

typeDefinition表

ID  | typeID | categoryID | typeName
=====================================
1   |  1     |    1       | Gloves
2   |  2     |    1       | Bats
3   |  3     |    2       | Shoes
4   |  4     |    2       | Footballs
Run Code Online (Sandbox Code Playgroud)

categoriesDefinition表

ID  | categoryID | catName
=============================
1   |  1         | Baseball Equipment
2   |  2         | Football Equipment
Run Code Online (Sandbox Code Playgroud)

我在想这个吗?两种方法都不能以相同的方式获得最终解决方案(后者只涉及几个连接以收集平面表,如图1所示)?

Bil*_*win 9

规范化的目的和好处是它使得输入异常数据变得更加困难(理想情况下,不可能).

例如,在图1中,有什么可以防止您意外地存储带有typeid 3和categoryid 1的行?除了编写非常完美的应用程序代码之外,没什么.

但是,如果您使用单表方法,并且您必须更改typeid 3的父类别,则必须更改数百万个位置的数据以反映更改.这意味着在执行清理时锁定表,否则可以同时插入新数据.

规范化有助于冗余地消除存储信息,并且如果每个离散事实(例如,typeid 3属于categoryid 2)仅存储一次,则很容易以原子方式进行更改,并且自动更改对该行的所有引用的含义.

你是对的,需要更多的连接 - 但只有你像你一样在整个地方使用伪oke.您不一定需要这样做,您可以使用自然键,并且使用级联外键声明对它们的引用,因此查找表中的更改也会自动更新引用表.

当然,规范化规则不要求使用伪讽刺.这些规则对他们一无所知.


重新评论:伪代码代理键是用于标识行的"id"列.通常,这些值是通过自动递增机制分配的,该机制确保唯一性,同时允许并发事务插入行.id的值对于它标识的行没有任何意义.


下面显示了您的表格在正常形式下的外观,但没有代理键.

productsOffered表

client | product        | customURL
===================================
Smith  | Rawlings Glove | 1111
Smith  | Product 2      | 2222
Smith  | Product 3      | 3333
Smith  | Product 4      | 4444
Jones  | Rawlings Glove | 5555
Jones  | Product 4      | 6666
Run Code Online (Sandbox Code Playgroud)

productsDefinition表

product        | type
=======================
Rawlings Glove | Gloves
Product 2      | Bats
Product 3      | Bats
Product 4      | Shoes
Run Code Online (Sandbox Code Playgroud)

typeDefinition表

type      | category
==============================
Gloves    | Baseball Equipment
Bats      | Baseball Equipment
Shoes     | Football Equipment
Footballs | Football Equipment
Run Code Online (Sandbox Code Playgroud)

categoriesDefinition表

category
==================
Baseball Equipment
Football Equipment
Run Code Online (Sandbox Code Playgroud)

它与关系数据库设计和规范化完全一致,使用非整数作为主键列的数据类型,因此外键从其他表引用它们.

为了性能或简洁或允许其他列中的值自由更改,有充分的理由使用代理键.但规范化并不要求使用代理键.