现在,据我所知,一般
数据规范化背后的原则是
创建一个RDBMS,其中数据
冗余被保持在最低限度。
嗯,好的。
在我的项目中,一位 DB 人员
创建了一个数据库。我们有 50 多张桌子,并且
数据库中的表通常非常
支离破碎,即一张桌子有两个或
三列就是这样。
桌子的数量并不能说明设计的好坏。有些企业需要一两个。其他人需要更多。我曾在财富 500 强的数据库中工作过,其中包含数千个表。
列数并不能说明设计的好坏。并且列数与碎片无关。我会说列相对较少的表通常是一个好兆头。并不总是一个好兆头,但通常是一个好兆头。
现在,说到编写 sql
查询,它已成为一种
小麻烦,因为每个查询都涉及
梳理了几种不同的
表并将它们连接在一起。一世
想知道这是不是一面
数据标准化的影响?或者确实
这指向别的东西?
这有两个不同的常见原因。
当您对表进行规范化时,您可以通过识别函数依赖关系、隔离一个或多个新表中的函数依赖列并将它们从原始表中删除来减少冗余(并提高数据完整性)。所以规范化一个表格,从一个较低的范式移动到一个较高的范式
- 总是增加
表,
- 总是减少列数
在原始表格中,并且
-
有时需要加入才能检索
人类数据。
另一种常见的做法是用 id 号替换字符串。这与标准化无关。 (没有“id number normal form”之类的东西。)用 id numbers 替换字符串
- 总是增加
表,
- 不改变列数
在原始表中(除非在
与归一化同时),
-
总是需要一个连接来为人类检索数据。
此线程的其他部分似乎有些混乱。我意识到,严格来说,以下内容均直接与 OP 的问题相关。
1NF 是“一值”原则。它与 row 是“原子的”没有任何关系。在关系模型中,atomic 不指代行;它指的是价值观。
“一个值”表示行和列的每个交集都包含一个值。 (换句话说,值是“原子的”。但是atomic这个词有一些不幸的含义,所以大多数现代从业者都避免使用它。)这个值不需要简单;它可以任意复杂。但是,如果它有自己有意义的部分,dbms 要么完全忽略这些部分,要么提供操作它们的函数。 (您不必编写函数来操作部件。)
我认为最简单的例子是日期。日期有部分,由年、月和日组成。 dbms 要么忽略这些部分(如SELECT CURRENT_DATE),要么提供操作它们的函数(如SELECT EXTRACT(YEAR FROM CURRENT_DATE))。
试图回避“一个值”原则会导致一个推论:“无重复组”原则。
重复组包含来自一个域的多个值,所有值具有相同的含义。所以像下面这样的表是一种重复组的例子。 (还有其他类型。)“phone_1”和“phone_2”的值来自同一个域,并且它们具有相同的含义——用户“n”具有电话号码(phone_1 和 phone_2)。 (主键是“user_id”。)
user_id phone_1 phone_2
1 (111) 222-3333 (111) 222-3334
2 (111) 222-3335 (111) 222-3336
但下一张表虽然非常相似,但没有重复组。这些值来自同一个域,但它们的含义不同。 (主键是“user_id”。)
user_id home_phone work_phone
3 (111) 222-3333 (111) 222-3334
4 (111) 222-3335 (111) 222-3336
2NF 是“全键”原则。它与键的数量无关;具有“n”列的表可能有“n”个键。 (例如,参见this other SO answer。)在关系模型中(以及,当您进行规范化练习时),如果您看到单词 key 本身,请认为“候选键”。
相反,2NF 与具有多列的候选键有关。当候选键有多个列时,2NF 要求每个非主属性在功能上依赖于每个候选键的所有列,而不仅仅是任何候选键的某些列。 (非主属性是不属于任何候选键的属性。)
以下示例改编自Wikipedia entry on 2nf。 (主键是 {employee, Skill}。)
Table: employee_skills
employee skill current_work_location
--
Jones Typing 114 Main Street
Jones Shorthand 114 Main Street
Jones Whittling 114 Main Street
Bravo Light Cleaning 73 Industrial Way
Ellis Alchemy 73 Industrial Way
Ellis Flying 73 Industrial Way
Harrison Light Cleaning 73 Industrial Way
虽然非主列 current_work_location 在功能上确实依赖于主键 {employee, Skill},但它在功能上也仅依赖于主键的一部分,即“员工”。该表不在 2NF 中。
您无法通过为每一行分配一个代理键来回避 2NF 问题。 (主键是 es_id;前一个主键 {employee, Skill} 有一个 UNIQUE 约束)。
Table: employee_skills
es_id employee skill current_work_location
--
1 Jones Typing 114 Main Street
2 Jones Shorthand 114 Main Street
3 Jones Whittling 114 Main Street
4 Bravo Light Cleaning 73 Industrial Way
5 Ellis Alchemy 73 Industrial Way
6 Ellis Flying 73 Industrial Way
7 Harrison Light Cleaning 73 Industrial Way
很明显,添加 id 号并没有消除部分依赖 employee->current_work_location。在不去除部分依赖的情况下,这个表仍然不在2NF中。
3NF 是“无传递依赖”原则。正如您从the Wikipedia example 中看到的那样,它不一定与派生或计算数据有关,在此处改编。 (主键是 {tournament, year}。此表不在 3NF 中。)
Table: tournament_winners
tournament year winner winner_date_of_birth
--
Indiana Invitational 1998 Al Fredrickson 21 July 1975
Cleveland Open 1999 Bob Albertson 28 September 1968
Des Moines Masters 1999 Al Fredrickson 21 July 1975
Indiana Invitational 1999 Chip Masterson 14 March 1977
两个依赖关系表明该表具有传递依赖关系。
- winner_date_of_birth 中的值
似乎在功能上取决于
首要的关键。每个主键值
确定一个且只有一个值
对于winner_date_of_birth。但 。 . .
- winner_date_of_birth 中的值
似乎在功能上也依赖于
优胜者。获胜者的每个价值
确定一个且只有一个值
对于winner_date_of_birth。
鉴于这两个明显的功能依赖关系以及对锦标赛、获胜者和出生日期这三个词的含义的理解,我们可以说那个
- 获胜者 -> 获胜者日期出生日期是
功能依赖,以及
- {tournament, year} -> 获胜者是一个函数依赖,并且
- {锦标赛,年份} ->
Winner_date_of_birth 是传递的
依赖。