有关关系数据库中的查找表的最佳实践是什么?


14

查找表(或某些人称为代码表)通常是可以为特定列提供的可能值的集合。

例如,假设我们有一个查找表party(用于存储有关政党的信息),该表具有两列:

  • party_code_idn,其中包含系统生成的数值,并且(缺少业务域的含义)可以用作实键的替代。
  • party_code是表的实键或“自然”键,因为它维护具有业务域内涵的值。

让我们说这样的表保留了以下数据:

 +----------------+------------+
 | party_code_idn | party_code |
 +----------------+------------+
 |              1 | Republican |
 |              2 | Democratic |
 +----------------+------------+

party_code列,这使价值“共和”和“民主”,在工作台的真正的关键,是建立了一个独特的约束,但我需要添加的party_code_idn,它定义为表(的PK虽然,从逻辑上说,party_code可以用作主键[PK])。

指向事务表中的查找值的最佳实践是什么?我是否应该建立外键(FK)引用(a)直接指向自然和有意义的值,或者(b)替代值?

例如,选项(a)

 +---------------+------------+---------+
 | candidate_idn | party_code |  city   |
 +---------------+------------+---------+
 |             1 | Democratic | Alaska  |
 |             2 | Republican | Memphis |
 +---------------+------------+---------+

具有以下属性1

  1. 可供最终用户阅读(+)
  2. 易于跨系统导入导出(+)
  3. 难以更改值,因为需要在所有引用表(-)中对其进行修改
  4. 添加新值并不昂贵(=)

我认为在应用程序编程术语中从函数调用中得出一个类比,几乎就像“ 按值传递 ” 。

例如,选项(b)

 +---------------+----------------+---------+
 | candidate_idn | party_code_idn |  city   |
 +---------------+----------------+---------+
 |             1 |              1 | Alaska  |
 |             2 |              2 | Memphis |
 +---------------+----------------+---------+

具有以下属性:

  1. 最终用户不可读(-)
  2. 难以进出口,因为我们需要取消引用(-)
  3. 易于更改值,因为我们仅将引用存储在事务表中(+)
  4. 添加新值并不昂贵(=)

如果与应用程序编程中的函数调用相比,它与“ 通过引用传递 ” 非常相似。

Import-Export也可以以其他方式完成,即,只需再次填充查找表,然后重新设置代理列即可。我希望我做对了,这是我刚刚听到的可能性。

1. 请注意+-=指出这些属性的好处。

非常重要的一点是:如果我们仅使用后一种方法,则查找(或代码)表与FK引用之间是否有区别?我认为它们的工作原理相同。

相关资源

Answers:


10

通过IDN,我想你的意思是一个IDENTITYSEQUENCE还是AUTO_INCREMENT场?您应该在这里这里看看。

注意,第一个参考的第5节(将数据值误用作数据元素)在图10下方

当然,您可以为销售人员提供一个单独的表,然后使用外键(最好使用上面显示的简单代理键,如sales_person_id)来引用该表。

因此,该专家认为您应该“尊重”代理密钥。它确实是一项基本的SQL技术,不会在您的日常SQL中引起问题。看来图10中有错误-SalesData中的sales_person应该是替代键(即数字),而不是文本。我从上面的引用中推断出这一点。

您应该不惜一切代价避免诱惑(对于新手数据库程序员来说是很常见的),以提交第(1)节通用查找表中概述的错误。这通常被称为MUCK(大规模统一代码密钥)方法(并非偶然:-),尤其是Joe Celko,也被讽刺地称为OTLT-一个真实查询表),并导致各种困难。新手程序员似乎觉得单个代码/查找/任何表都“更干净”,并且如果事实与事实没有任何距离的话,它将效率更高。

根据上面的第二个参考:

规范化消除了冗余数据,从而使执行数据完整性的任务变得非常简单,但是创建MUCK的过程完全是另外一回事。MUCK不会消除冗余数据,而是消除了认为是冗余表的内容,但是正如我将演示的,更少的表并不等于简单。

您可能还想看看我在这里处理的相关EAV(实体属性值)范例。


IDN是指自动生成的外键。我不使用通用查找表,不知道您如何看待我?实际上,我们实际上使用了数百个代码表。似乎有人在统一表中执行此操作确实很奇怪。但是很高兴知道存在这种模式,应该避免这种模式。EAV似乎很有趣。因此,共识是我应该使用IDN(即代理密钥)取消引用?
Nishant

1
“取消引用”策略显然是多数方法。为什么不尝试一下,看看自己过得如何?选择一些自然键,看看您的SQL如何工作-然后指定一个替代项并弄乱它一段时间。Celko和Pascal在SQL / Relational世界中会受到尊重,但是我看到有人在与他们争论说他们的方法太过规范和过于纯粹-“现实世界”系统必须使用代理键。如果您的自然键是三个字段,而FOREIGN KEY在另一个表中又是一个,那么它可能会变得很混乱,但是YMMV。
Vérace

是的,我的想法很纯粹,我就像为什么要使用代理键!然后,在纯粹主义者的世界中,某些用例似乎真的很难处理。我觉得尽管您有导入和导出的一些缺点,但是替代方法更容易一些。确实,合并方案可能会更加棘手。在代理方案中,Btw代码表与外键没有太大区别吗?我的意思是存在逻辑区别,但只有外键。
Nishant

1
您可以通过UNIQUE CONSTRAINTs和NOT NULLs 强制执行自然键-很好,您的代码表条目FOREIGN KEY位于使用/引用它们的表中的s-因此概念是相关的,但并不相同。代码表的替代键是出现在“子”表中的字段-当然不太清晰,但INT不是很大-不需要太多空间,这是替代键的优点。
Vérace

10

第三种方法具有两个选项的某些优点-将实际代码放入代码表中。我的意思是指一个简短的字符序列,它抓住了全部价值的本质,而且是独一无二的。对于您给定的示例,可能是

Idn: 1
Name: Democrats
Code: D      (or DEM)

该代码作为外键携带在事务表中。它简短,可理解并且在某种程度上与“真实”数据无关。名称的递增更改不会提示代码更改。共和党是否应逃之夭夭集体,然而,代码的改变可能是必要的,以及伴随而来的问题,代孕的ID会不会产生。

这种样式被称为缩写编码。我可以推荐Celko在这方面的著作。Google图书举几个例子。搜索“ Celko编码”。

其他示例:国家的2或3个字母编码,货币代码的3个字母编码(GBP,USD,EUR)。简短,不言自明且不变(它们有一个ISO)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.