收集三层信息:
该层包含具有UNIQUE
自然索引的数据和易于传输的代理密钥。
Table Surnames:
+-----------------------------+--------------+
| ID (Auto Increment, PK) | Surname |
+-----------------------------+--------------+
| 1 | Smith |
| 2 | Edwards |
| 3 | Brown |
+-----------------------------+--------------+
Table FirstNames
+-----------------------------+--------------+
| ID (Auto Increment, PK) | FirstName |
+-----------------------------+--------------+
| 1 | John |
| 2 | Bob |
| 3 | Mary |
| 4 | Kate |
+-----------------------------+--------------+
自然键
或者,ID
如Mike
Sherrill所解释的,上面的两个表可以不存在,并且可以使用Surname和FirstName作为自然主键。在这种情况下,假设参考下面的图层varchar
而不是int
。
在这一层中,使用了复合索引。该值可以是UNIQUE
或PRIMARY
,取决于是否将替代键用作主键。
+-----------------+--------------+
| FirstName | LastName |
+-----------------+--------------+
| 1 | 2 |
| 1 | 3 |
| 2 | 3 |
| 3 | 1 |
| 4 | 2 |
| ... | ... |
+-----------------+--------------+
在这一层中,通过ParentsOf
表探索人与人之间的关系。
ParentsOf
+-----------------+-----------------+
| Person | PersonParent |
+-----------------+-----------------+
OR
+-----------------+-----------------+-----------------+-----------------+
| PersonFirstName | PersonSurname | ParentFirstName | ParentSurname |
+-----------------+-----------------+-----------------+-----------------+
假设引用完整性对我来说非常重要,并且我将拥有FOREIGN KEYS
这些索引,以便我可以在这方面让数据库负责监视其自身的完整性,并且如果我要使用ORM,它将像Doctrine这样的人,它对复合主键具有本地支持…
请帮助我了解:
在第一层上使用代理密钥与自然密钥进行权衡的列表。
在第二层利用复合密钥与代理密钥进行权衡的清单,这些密钥可以转移到第三层。
我对听到更好的消息不感兴趣,因为我知道专业人员之间在该主题上存在重大分歧,这将引发一场宗教战争。相反,我要问的是,尽可能简单和客观地实现,这是通过将代理密钥传递给每个图层而不是保持主密钥(自然/复合或代理/复合)来实现的。任何人都可以在SO和其他网站上找到说
永远不 使用或 永远 使用代理密钥的人。相反,在您的回答中,我将最欣赏折衷的合理分析。
编辑:
已经指出,姓氏示例对于使用6NF而言是一个较差的示例。为了使问题完整无缺,我将保留它。如果您在构想此用例时遇到困难,最好使用“杂货项目”列表。又名:
+-----------------------------+--------------+
| ID (Auto Increment, PK) | Grocery |
+-----------------------------+--------------+
| 1 | Sponges |
| 2 | Tomato Soup |
| 3 | Ice Cream |
| 4 | Lemons |
| 5 | Strawberries |
| 6 | Whipped Cream|
+-----------------------------+--------------+
+-----------------------------+--------------+
| ID (Auto Increment, PK) | Brand |
+-----------------------------+--------------+
| 1 | Bright |
| 2 | Ben & Jerry's|
| 3 | Store Brand |
| 4 | Campbell's |
| 5 | Cool Whip |
+-----------------------------+--------------+
自然复合关键示例:
+-----------------------------+--------------+
| Grocery | Brand |
+-----------------------------+--------------+
| Sponges | Bright |
| Ice Cream | Ben & Jerry's|
| Ice Cream | Store Brand |
| Tomato Soup | Campbell's |
| Tomato Soup | Store Brand |
| Lemons | Store Brand |
| Whipped Cream | Cool Whip |
+-----------------------------+--------------+
推荐配对
+-----------------+-----------------+-----------------+-----------------+
| Grocery1 | Brand1 | Grocery2 | Brand2 |
+-----------------+-----------------+-----------------+-----------------+
重申一下,这也只是一个例子。这不是我建议继续进行的方式,但是应该可以帮助说明我的问题。
该方法存在不足之处。我要重申的是,这个问题是要求您逐步了解以下每种方法的优缺点,而不是强调一种方法优于另一种方法。我相信大多数人能够超越这个特定示例的可疑性质来回答核心问题。此编辑适用于那些无法编辑的内容。
下面有一些很好的答案,如果您对该走的方向感到好奇,请阅读它们。
结束编辑
谢谢!
这里有一些权衡:
所有子表外键只需要一个列即可引用主键。
非常容易更新表中的自然键,而无需使用外键更新每个子表
较小的主键/外键索引(即,非宽键索引)可以使数据库运行更快,例如,当删除父表中的记录时,需要搜索子表以确保不会创建孤儿。窄索引的扫描速度较快(仅凭外观即可)。
您将拥有更多索引,因为您很可能还希望对数据中存在的任何自然键进行索引。
数据库中的索引更少
数据库中的列较少
更容易/更快地插入大量记录,因为您无需抓住序列生成器
更新化合物中的键之一要求还更新每个子表。
我只发现了一个有意义的实例。当您需要标记每个表中的每个记录以提高行级安全性时。
例如,假设您有一个数据库,该数据库存储了50,000个客户端的数据,而每个客户端都不应该看到其他客户端的数据-这在Web应用程序开发中很常见。
如果每个记录都用client_id
字段标记,则您正在创建行级安全性环境。大多数数据库都有正确设置时可以强制执行行级安全性的工具。
首先要做的是设置主键和外键。通常,具有以id
字段为主键的表。通过添加client_id
密钥,现在是复合密钥。并且有必要携带client_id
到所有子表。
组合密钥基于2个代理密钥,是一种防弹方式,可确保客户端之间以及整个数据库内的数据完整性。
此后,您将创建视图(或使用Oracle EE设置虚拟专用数据库)或其他各种结构,以允许数据库强制执行行级安全性(这是其所有主题)。
可以肯定的是,此数据结构不再归一化为n级。client_id
每个pk /
fk中的字段会反规范化原本正常的模型。该模型的好处是易于在数据库级别强制执行行级别的安全性(这是数据库应该执行的操作)。每次选择,插入,更新,删除都限于client_id
当前设置的会话。该数据库具有
会话意识 。
替代键始终是安全的选择。他们需要更多的工作来设置并需要更多的存储空间。
我认为最大的好处是:
能够立即更改一个表和所有其他子表中的PK,而无需任何操作。
当数据混乱时-有时由于编程错误,代理密钥会使清理变得容易得多,在某些情况下,由于存在代理密钥,因此只能进行清理。
由于数据库能够搜索属性以找到s.key,然后通过单个数字键联接所有子表,因此查询性能得到了改善。
自然键(尤其是复合NKey)使编写代码变得很痛苦。当您需要连接4个表时,“ where子句”将比使用单个SKey时更长(并且更容易弄乱)。
代理密钥是“安全”的途径。自然键在某些地方很有用,我会说数据库中大约1%的表。
我有一个表,其中有3个属性作为主键产品:primary key(,,)。 现在我在另一个表中引用这个复合主键 order_details:外键(product_name,product_type,category)引用产品(product_name,product_type,category) 然而,我在控制台中得到一个错误,说缺少括号,我无法添加外键。但是,如果只在引用中添加两个列名(例如:“F
我有以下MySQL表。这里的思想是轨道和课程是主键。并且轨道中的一个航向可能依赖于“同一轨道”中的另一个航向,因此我在(,)上创建了一个复合FK 但我在“depends_on_course_id column”中得到的结果都是空的,我猜getTrackCourse方法的映射有问题,但我不知道是什么?非常感谢任何帮助。
模板实体: 工作流实体: 指挥实体:
本文向大家介绍Spring整合Redis完整实例代码,包括了Spring整合Redis完整实例代码的使用技巧和注意事项,需要的朋友参考一下 做过大型软件系统的同学都知道,随着系统数据越来越庞大,越来越复杂,随之带来的问题就是系统性能越来越差,尤其是频繁操作数据库带来的性能损耗更为严重。很多业绩大牛为此提出了众多的解决方案和开发了很多框架以优化这种频繁操作数据库所带来的性能损耗,其中,尤为突出的两个
本文向大家介绍DBMS中的安全性,完整性和授权,包括了DBMS中的安全性,完整性和授权的使用技巧和注意事项,需要的朋友参考一下 数据库安全性数据库安全性具有许多不同的层,但是关键方面是: 认证方式 用户身份验证是为了确保访问数据库的人是他声称的身份。身份验证可以在操作系统级别甚至数据库级别本身进行。许多身份验证系统(例如视网膜扫描仪或生物识别技术)用于确保未经授权的人员无法访问数据库。 授权书 授
我有和表,我在laravel中建立了一对一的关系,这很好,但如果我尝试在不引用任何用户(id)的情况下手动将数据(外键用户id)添加到电话表中,它也会起作用。 在mysql(phpmyadmin)中,迁移后没有建立外键关系。 所以我想问,外键的优势是什么,如果它不把任何约束放在数据库表中,或者如果有任何方法可以使用laravel添加这些约束,请告诉我。 代码片段 app/Phone.php app