Nis*_*ant 16 foreign-key database-design best-practices primary-key
查找表(或一些人称之为代码表)通常是可以为特定列给出的可能值的集合。
例如,假设我们有一个名为party
(用于存储有关政党的信息)的查找表,它有两列:
party_code_idn
,它保存系统生成的数值,并且(缺乏业务领域含义)用作真实键的代理。party_code
, 是表的真实或“自然”键,因为它维护具有业务领域内涵的值。让我们说这样的表保留了以下数据:
+----------------+------------+
| party_code_idn | party_code |
+----------------+------------+
| 1 | Republican |
| 2 | Democratic |
+----------------+------------+
Run Code Online (Sandbox Code Playgroud)
在party_code
列,这使价值“共和”和“民主”,在工作台的真正的关键,是建立了一个独特的约束,但我需要添加的party_code_idn
,它定义为表(的PK虽然,从逻辑上说,party_code
可以作为 PRIMARY KEY [PK])。
指向事务表中的查找值的最佳实践是什么?我应该建立外键 (FK) 引用(a)直接指向自然和有意义的值还是(b)代理值?
选项(a),例如,
+---------------+------------+---------+
| candidate_idn | party_code | city |
+---------------+------------+---------+
| 1 | Democratic | Alaska |
| 2 | Republican | Memphis |
+---------------+------------+---------+
Run Code Online (Sandbox Code Playgroud)
具有以下属性1:
我认为这几乎就像“按值传递”,从应用程序编程术语中的函数调用中进行类比。
选项(b),例如,
+---------------+----------------+---------+
| candidate_idn | party_code_idn | city |
+---------------+----------------+---------+
| 1 | 1 | Alaska |
| 2 | 2 | Memphis |
+---------------+----------------+---------+
Run Code Online (Sandbox Code Playgroud)
具有以下属性:
如果与应用程序编程术语中的函数调用相比,它与“通过引用传递”非常相似。
导入-导出也可以用不同的方式完成,即,只需再次填充查找表,然后重新设置代理列。我希望我做对了,这是我刚刚听说的一种可能性。
1. 注意+
,-
并=
指出这些属性的好处。
非常重要的是:如果我们只想使用后一种方法,查找(或代码)表和 FK 引用之间有区别吗?我认为它们的工作原理相同。
Mic*_*een 12
第三种方法具有您的两个选项的一些优点 - 将实际代码放入代码表中。我的意思是一个简短的字符序列,它捕捉了完整价值的本质并且是独一无二的。对于您给定的示例,它可能是
Idn: 1
Name: Democrats
Code: D (or DEM)
Run Code Online (Sandbox Code Playgroud)
代码作为外键携带到事务表中。它简短、易懂,并且在某种程度上独立于“真实”数据。对a 名称的增量更改不会暗示代码更改。共和党是否应逃之夭夭集体,然而,代码的改变可能是必要的,以及伴随而来的问题,代孕的ID会不会产生。
这种风格被称为缩写编码。我可以推荐 Celko 在这方面的写作。谷歌图书有几个例子。搜索“Celko 编码”。
其他示例:国家/地区的 2 或 3 个字母编码,货币代码的 3 个字母编码(GBP、USD、EUR)。简短、不言自明且不会改变(并且它们有一个 ISO)。
Idn、Code 和 Name 中的每一个都是唯一的,因此每个都是候选键,并且可以选择任何一个作为主键。因此,对于给定 Idn 的示例,可以从表定义中删除,而使用代码。不同的 DBMS 以自己的方式处理整数和字符串,因此可能存在性能方面的考虑。在某些表中将 Idn 作为 FK 而在其他表中使用 Code 作为 FK 可能很有用。
Vér*_*ace 11
通过IDN
,我认为您的意思是IDENTITY
,SEQUENCE
或AUTO_INCREMENT
字段?你应该看看这里和这里。
注意,第 5 节(误用数据值作为数据元素),在图 10 下方
当然,您可以为销售人员创建一个单独的表,然后使用外键引用它,最好使用简单的代理键,如上所示的 sales_person_id 。
所以,这位专家认为你应该“尊重”代理键。它确实是一种非常基本的 SQL 技术,不会在您的日常 SQL 中引起问题。图 10 中似乎存在错误 - SalesData 中的 sales_person 应该是代理键(即数字),而不是文本。我从上面的引文中推断出这一点。
您应该不惜一切代价避免犯下第 (1) 节通用查找表中概述的错误的诱惑(对于新手数据库程序员来说非常常见)。这通常被称为 MUCK(大规模统一代码密钥)方法(并非偶然:-),尤其是Joe Celko,也被讽刺地称为OTLT - 一个真正的查找表)并导致各种困难。新手程序员似乎觉得单个代码/查找/任何表都是“更干净”的,并且在没有什么比事实更远的情况下会更有效率。
从上面的第二个参考:
规范化消除了冗余数据,从而使强制执行数据完整性的任务变得更加简单,但创建 MUCK 的过程完全是另一回事。 MUCK 不会消除冗余数据,而是消除了被认为是冗余表的内容,但是正如我将要展示的,更少的表并不等于简单。
您可能还想查看我在此处处理的相关 EAV(实体属性值)范例。
归档时间: |
|
查看次数: |
10853 次 |
最近记录: |