问题 数据库设计 - COUNTRY,CURRENCY int或varchar的主键


  • 对于我的国家表,我使用了 国家代码作为主键“AU, 美国,英国,法国“等

  • 对于我的货币表,我使用货币代码作为主键“AUD,GBP,USD”等

我认为我所做的是好的,但另一位开发人员希望我将所有主键更改为int,因为国家代码,货币代码可能在将来的某个时候发生变化。我们只是不知道,在这种情况下他是对的,他的道路是最安全的道路。

我应该将主键更改为int是安全的而不是抱歉吗?我不能保留它吗?


9311
2018-02-02 06:17


起源

你不一定要成为一个 INT  - 但如果保持不变,我一定会确保使用 CHAR(3) (不 VARCHAR!)这些代码。 - marc_s


答案:


我会使用带有char列的ISO代码。

如果一个国家分裂,那么你将获得新的ISO代码(比如SC,WL,EN),但英国将会 仍然有效 对于历史数据。

货币也一样。 2000年的交易将采用货币 那时候:法国法郎,德国马克,比利时香蕉,但不是欧元。


13
2018-02-02 07:46



+1必须像“比利时香蕉”;-) - marc_s
“英国仍将对历史数据有效” - 遗憾的是,这在ISO 3166-1 alpha-2中可能不正确。例如,“CS”代表捷克斯洛伐克直到1993年,塞尔维亚和黑山代表2003年至2006年之后的一段时间。但ISO表示,在重新使用退役代码之前至少还有5年时间。 - Jan Żankowski


我会说,“一个国家的诞生”或者一种货币的消失 - 总的来说 - 是一种相当罕见的事件 - 每年不可能一年发生几次。

所以在这方面,我认为使用ISO定义的国家和货币代码作为主键应该没问题。

是的,如果欧元区出现问题,或者另一个国家被分成两个,你可能需要做一些手工管理 - 但是你必须这样做 INT 同样。在这样的情况下,我会争辩说一个人工代理键​​(就像这样 INT)实际上只增加了开销,并没有真正帮助保持事情更容易/更明确。

由于这些代码非常短,通常长度相同,但我建议使用 CHAR(3) 要么 CHAR(5)  - 使用没有意义 VARCHAR 对于这样一个短字符串,并且VARCHAR作为可变长度字段的行为完全不同(并且在性能方面不是“更好”)固定长度字段 INT 要么 CHAR


3
2018-02-02 06:28





从逻辑的角度来看,添加代理意味着额外的列,额外的键约束和更复杂的逻辑来查询和操作数据。这是一件需要考虑的事情。

从物理角度来看,在SQL Server中,INTEGER键占用的空间是CHAR(2)或CHAR(3)的两倍多。这意味着您的引用表和索引会变大。它还使这些外键值的任何更新都更加昂贵。我不知道您的数据,但很可能这些外键列中的引用数据可能比父表中的国家/地区代码和货币代码值更频繁地更新。相比之下,货币和国家的ISO代码几乎从未改变,因此可能很少担心。通过更改为INTEGER键,您可以很好地完成 增加 更新这些外键值的成本。

如果您正在考虑将此类更改作为性能优化,那么我建议您非常仔细地评估INTEGER密钥是否会使这些值的更新成本更高或成本更低。我建议你忽略那些说“永远做X”的人。 Dogma在数据库设计方面没有帮助。评估实际影响,并做出相应的决定。


3
2018-02-03 01:17





我认为,在关于国家和货币代码的ISO标准之前,您的系统将会过时十次。

所以我真的认为使用01010101 01010011或21843而不是“US”没有任何好处。


1
2018-05-12 12:36





只要声明引用这些主键的任何外键,就可以使用 ON UPDATE CASCADE, 谁 管它 如果这些代码改变了?

查询任何引用表还有一个额外的好处 - 如果您只需要国家/货币代码,那么就不需要加入这些表 - 您已经获得了这些表中包含的代码。


如果您决定转移到INT代理,请记住仍然在这些列上放置一个唯一的约束 - 它们是这些表的真正关键。


0
2018-02-02 07:46



你关心,因为你真的不想通过级联更新来更新100,000,000条记录。切勿使用任何可以更改为主键的内容。我同意你的第二个陈述。 - HLGEM


我会使用INT ID作为键而不是ISO代码,并解释原因:

我工作的组织使用“自有货币”(LBP) - 例如,当用户执行某些交易时,他会收到一定数量的LBP作为奖金。此外,他可以将这些LBP兑换成美元,欧元等,反之亦然,用LBP等支付服务费。另外,我没有在ISO标准中找到BTC(比特币)货币。

是的,这些不是官方货币,但从系统和用户的角度来看,它更灵活地将它们作为货币而不是用户可以买卖的额外产品。

我工作的组织不使用INTS作为主键,他们使用ISO代码作为ID(加上那些额外的货币)。

据官方统计,LBP是黎巴嫩镑的ISO标准 - 因此他们无法顺利将黎巴嫩镑添加到系统中。

如果您按代码识别您的货币,并且将来某些新货币将被注册为ISO标准(例如,LBE或BTC) - 那么这些货币将与“您的”货币冲突。

有人在这里提到,为货币设置额外的int键是一个额外的索引。 但对不起,300条记录(大致的货币数量)是一个问题吗?此外,如果您使用INT作为货币的主键,它还有一个额外的好处:想象一个包含1M交易的表,其中包含金额和货币,以及什么更有效:INTS或CHARS?

所以我会选择INT。


0
2017-12-16 17:00





是的,在为时已晚之前,更改为整数键是一个好主意。

例如。如果英国加入欧元区怎么办?


-2
2018-02-02 06:20



永远不会发生..... :-) - marc_s
好吧,如果希腊离开它会怎么样:P - Hamish
好吧,在那之前他们是英镑和欧元。 - PerformanceDBA
如果您在记录金融交易时使用货币密钥,则绝不会更新代码。否则您的所有历史数据都将被破坏! - ianaré
当然,您使用正确的密钥来记录历史记录。 - Hamish


使用某些东西作为改变的主键是一种不好的做法。假设值已更改,然后您必须更新所有子记录。这样做可能会将数据库锁定数小时甚至数天。这就是为什么具有自然键上的唯一索引的整数FK对于易失性信息是更好的实践。


-2
2018-02-02 20:14



任何密钥都可能需要更改(无论是否为整数)。最安全的策略是假设任何密钥可能需要在某个时刻进行更改。相对稳定性是一个明智的标准,基于你选择的键,但“不变性”不是。 - sqlvogel
这是事实,但国家代码永远不会改变。如果订单发往某个国家/地区,您将保持该记录不变。即使国家拆分或更改,在订单发货时代码也是正确的。稍后更改它将使历史数据无效。在某些情况下,这甚至可能是非法的(可能适用数据预防法)。 - ianaré