问题描述
阅读有关规范化的内容后,我不确定如何解释 1 NF 要求
根据维基百科,如果“每个属性的域只包含原子不可分割的值”
我的问题是:
谁决定什么是不可分割的?
您可以将日期数据类型划分为年、月、日、秒、纳秒。您也可以将地址划分为精确的纬度坐标。你什么时候才能确定你已经达到了 1NF?
这个表会被认为是 1NF 吗?
全名 | 完整地址 |
---|---|
乔·佐威森 | 87th Victoria Street London EC96 1MB,14584 |
梅森汉堡 | 47th Jeremy Street London EC26 1MB,13584 |
德德里克·特里 | 27th Burger Street London EC16 1MB,17584 |
我在这里的解释是,对于列 fullName,值 Joe Zowesson 是不可分割的。而且邮政编码、街道号码和街道名称都是原子与列名 fullAddress 相关的。
我几乎可以肯定我错了,但我还不明白为什么。
问题是关于即将举行的考试,我将需要“证明”当前某事物处于哪种正常形式。根据您对原子一词的解释,我觉得这很困难。
解决方法
你基本上误解了1NF的概念。原子值意味着当你有一列 Name 时,你不应该在它旁边存储任何其他值。换句话说,用于 Name 的列不应与 Name 一起存储 ID、Address 或其他任何内容,这样当您查询 Name
列时,您只会得到 Name
,而不是带有 Id
或 Address
的名称。 姓名可以是您想要的任何形式,无论是名字+姓氏还是名字+姓氏+中间名+前名 .
是否需要为相关数据单独列的决定应在设计期间做出。假设您有 Student 表:
StudentId | 全名 | 地址 | 平均成绩 |
---|---|---|---|
1 | 约翰完成 | 美国纽约 | 3.4 |
2 | 罗伯特无聊 | 美国纽约 | 0 |
3 | 学生姓名 | 美国达拉斯 | 1 |
4 | 另一个LName | 德国慕尼黑 | 2 |
在这种情况下,这意味着您不需要单独编写查询,也不需要基于名字、姓氏的数据,而是一次性需要所有数据,例如:
SELECT FullName
FROM Student
WHERE StudentId = 1;
约翰完成
而当您单独需要 First name,Last name
时,您将它们分解成几列,例如:
StudentId | 全名 | 姓氏 | 地址 | 平均成绩 |
---|---|---|---|---|
1 | 约翰 | 完成 | 美国纽约 | 3.4 |
2 | 罗伯特 | 无聊 | 美国纽约 | 0 |
3 | 学生 | LName | 美国达拉斯 | 1 |
4 | 另一个 | LName | 德国慕尼黑 | 2 |
您的查询可能如下所示:
SELECT LastName,AverageGrade
FROM Student
WHERE AverageGrade >= 1 AND FirstName != 'John';
结果将是:
| LastName | AverageGrade |
---------------------------
| LName | 1 |
| LName | 2 |
或者类似的东西:
UPDATE Student
SET AverageGrade = 4
WHERE LastName = 'LName' AND FirstName != 'Student'
基本上,该决定取决于您如何操作数据以及您需要它以何种形式。
总结一下。关系是否在 1NF 中取决于您尝试在此表上存储什么值,正如我上面提到的,一个列应该只存储一种类型的值 ,例如ID、地址、姓名等。列值的外观取决于设计以及您需要存储数据的方式。如果你不需要分别查询fistname、middlename、lastname、secondname,那么你可以做的就是将它们全部保存在一列FullName中,它仍然是在 1NF。但是如果你分别需要它们,你可以将它们存储在单独的列中,它仍然是 1NF,但它可能违反其他规则。
以下是一些您可能会觉得有用的教程:https://www.studytonight.com/dbms/first-normal-form.php
,让应用程序及其使用方式指导您将哪些数据进一步拆分为其他字段(或不拆分)。
例如; 如果在您的应用程序中,您不断地将名字与姓氏分开,以便您可以在通信中说“Hi Joe”,那么您应该将 fullName 拆分为两个字段。相反,如果您有两个字段 firstName 和 lastName,并且总是将它们连接起来以便正确寻址信封,那么将这两个字段存储在表中的单个列中会更有意义。
在实践中,考虑到这两种情况的普遍性,数据库显示一些非规范化的情况并不少见,但风险是如果有人更新名字(例如)但没有同步'不更新全名。
考虑诸如如果您决定使用单列 fullName,您将如何强制您的用户遵循特定模式。如果您的应用程序需要“Joe Smith”,您将如何防止“Smith,Joe”?
日期是另一个很好的例子,同样,是否将这些部分分成单独的列取决于它们的使用方式。
指示何时插入行的日期时间字段可能不需要拆分,但如果您有许多只对年份感兴趣的查询(例如),将其拆分可能是有意义的。
这只是触及了表面,这就是为什么这个答案更多地是关于如何思考潜在问题。是的,出于各种原因,标准化您的数据库很重要,但您能走多远取决于您的数据在一天结束时的使用方式。