使用列的值(而不是数字ID)作为外键引用

时间:2014-05-23 19:38:31

标签: sql database oracle

不确定如何在标题中表达这一点。所以这是交易:我有一个表格,用于存储有关外汇汇率使用的货币对的信息:

PAIR_ID | BASE_CURRENCY | TERM_CURRENCY | ATTRIBUTE1 | ATTRIBUTE2 ...

理想情况下,我应该有另一个表来存储货币符号(主数据),比如CURRENCY_SYMBOLS和来自BASE_CURRENCYTERM_CURRENCY的外键到此表。但是我对这里有两种可能的方法感到困惑。

方法1

CURRENCY_PAIRS

PAIR_ID | BASE_CURRENCY_ID | TERM_CURRENCY_ID | ATTRIBUTE1 | ATTRIBUTE2 ...

CURRENCY_SYMBOLS

SYMBOL_ID | SYMBOL

BASE_CURRENCY_ID& TERM_CURRENCY_ID引用SYMBOL_ID

方法2 :而不是让symbol_id真正增加任何价值,而不是:

CURRENCY_PAIRS

PAIR_ID | BASE_CURRENCY | TERM_CURRENCY | ATTRIBUTE1 | ATTRIBUTE2 ...

CURRENCY_SYMBOLS

SYMBOL

BASE_CURRENCY& TERM_CURRENCY直接引用SYMBOL

我不确定哪一个更好,方法1似乎理想但实际上没有优势 - 实际上在我的所有查询中都需要额外的连接来检索数据。

方法2似乎更有效但不知何故不正确。

我应该选择哪一个指针?

3 个答案:

答案 0 :(得分:1)

在这两种情况下,您都需要加入,因此您不会保存加入。

选项1添加ID。此ID将默认具有聚簇索引。这意味着数据在磁盘上排序,其中ID最低,最后ID最高。这是一个灵活的选项,可以方便将来的开发。

选项2会将符号硬编码到货币对表中。这意味着如果您以后想要在符号表中添加另一列,例如进行分组,则需要创建symbol_id字段并更新货币对表中的所有记录。这增加了维护成本。

我总是为这种表添加int ID字段,因为开销很低,维护也更容易。

选项1还有索引优势

答案 1 :(得分:1)

方法2起初似乎是一个好主意,但它有一些问题。我会列出所有内容,即使1和2并不真正适用于您,因为您只使用3位ISO代码:

  1. 外键引用可占用更多空间。根据您需要制作VARCHAR的时间长短,它们可以占用更多空间作为外键,比如一个字节或一个短字。如果你有数以万计的对象引用这些外键,那么它就会加起来。一些数据库很聪明,并在引用表中用哈希表引用替换VARCHAR,但有些数据库并不是这样。没有DB在100%的时间都很聪明。
  2. 您必须将数据库密钥(至少对最终用户没有任何意义)暴露为业务密钥。如果老板想要替换" USD&#,该怎么办? 34;用" $"或"美元"?在这种情况下,您需要添加一个查找表,否定了首先使用此方法的主要原因。否则,您需要更改CURRENCY_SYMBOLS中的值,这可能很棘手(参见#3)。
  3. 很难维护。国家偶尔会改变。他们在进入/离开欧元,政变等时改变货币。有时只是货币的名称在政治上变得不正确。使用这种方法,您不仅需要更改CURRENCY_SYMBOLS中的条目,还要将该更改级联到引用它的DB中的每个对象。那可能非常慢。此外,由于您没有常量键,程序员硬连接到其业务逻辑的键是这些相同的键,现在已经改变。祝你们在整个代码库中寻找所有代码,祝你好运。
  4. 我经常使用" hybrid"办法;也就是说,我使用方法1但使用非常短的VARCHAR作为ID(最多3或4个字符)。这样,每个条目都可以有一个" SYMBOL"暴露给最终用户的字段,可以通过简单地修改一个表条目来根据需要进行更改。此外,开发人员的ID有点比尝试记住" 14"是日元和" 27"是美元。由于这些密钥没有公开,只要开发人员记得YEN是大革命之前的货币,他们就不必改变。如果查询只是针对业务逻辑,那么您仍然可以通过不使用连接来逃避。对某些事情来说速度较慢但对其他事情来说速度更快。 YMMV。

答案 2 :(得分:1)

我建议使用符号id,但它很接近。这假设您实际上是指货币缩写,而不是符号。我通常更喜欢代理数字键。如果我必须使用字符串,那么我想避免使用国际字符。

一个问题是处理可能不是国际标准或可能随时间变化的货币。在过去15年中,我们看到许多货币变化,主要是欧元。但是你有其他情况,例如土耳其里拉被重新评估。因此,如果您使用自己的定义,则可能无法区分这两种货币。

此外,根据您的申请,如果不是官方货币,您可能会将某种东西称为“货币”。当金融产品使用某种货币(或其他基准指标)定价时会发生这种情况,但您希望以与系统中其他债券相同的方式对待“货币篮子债券”。

因为货币问题比我想象的要复杂得多,所以我倾向于使用代理键来为应用程序提供更大的灵活性。