数据库设计 - 国家主键,货币int还是varchar

13
  • 我使用国家代码作为主键,例如“AU、US、UK、FR”等,在我的国家表中。

  • 我使用货币代码作为主键,例如“AUD、GBP、USD”等,在我的货币表中。

我认为我的做法没问题,但另一位开发人员要求我将所有主键都改成整数,因为他说国家代码和货币代码未来可能会更改。我们并不知道这一点,但在这种情况下,他是正确的,他的方法是最安全的。

我应该将主键改为整数以确保安全吗?还是可以保持原样?


3
您不一定需要将其设置为 INT 类型 - 但如果您保持原样,建议使用 CHAR(3)不是 VARCHAR!) 来存储这些代码。 - marc_s
8个回答

18

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

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

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


2
"UK仍然适用于历史数据" - 不幸的是,在ISO 3166-1 alpha-2中可能不正确。例如,“CS”代表捷克斯洛伐克直到1993年,从2003年后的一段时间代表塞尔维亚和黑山,直到2006年。然而,ISO表示退役代码将在重新使用之前至少有5年的时间。 - Jan Żankowski

4
我认为“国家的诞生”或货币的消失总的来说是相当罕见的事件,不太可能每年发生好几次。
因此,在这方面,使用ISO定义的国家和货币代码作为主键应该是可以的。
如果欧元区出现问题,或者另一个国家分裂成两个,你可能需要进行一些手动清理,但是使用INT也需要这样做。在这种情况下,我认为人造代理键(如INT)只会增加开销,而不真正有助于保持事物更容易/更明确。
由于这些代码非常短,并且通常长度相同,因此我建议使用CHAR(3)CHAR(5) - 没有必要为这么短的字符串使用VARCHAR,而且,可变长度字段(如VARCHAR)的行为与定长字段(如INTCHAR)非常不同(在性能方面并不“更好”)。

4

从逻辑角度来看,添加代理键会增加列、附加键约束和更复杂的数据查询和操作逻辑。这是需要考虑的一点。

从物理角度来看,在SQL Server中,整数型的主键所占用的空间是CHAR(2)或CHAR(3)的两倍以上。这意味着引用表和索引将变得更大。它还使得对那些外键值进行任何更新都变得更加昂贵。我不知道您的数据情况,但引用那些外键列中的数据可能比父表中的国家代码和货币代码值更新得更频繁。相比之下,货币和国家的ISO代码几乎永远不会更改,因此可能不必太担心。通过更改为整数型主键,您很可能会增加更新那些外键值的成本。

如果您正在考虑将其作为性能优化而进行这样的更改,则建议您非常仔细地评估INTEGER主键是否会使这些值的更新成本更高或更低。我建议您忽略那些说“总是要做X”的人。教条在数据库设计中没有帮助。评估实践中的真正影响,并根据此进行决策。


1
我认为,在ISO标准关于国家和货币代码制定之前,你的系统将会过时十倍。
因此,我真的看不出使用01010101 01010011或21843代替“US”的任何好处。

0
只要引用这些主键的任何外键都声明了 ON UPDATE CASCADE,那么这些代码改变谁会在意呢?
查询任何引用表格还有一个额外的好处 - 如果你只需要国家/货币代码,那么就不需要连接到这些表格 - 你已经在这些表格中包含了代码。

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


你很在意,因为你不想用级联更新来更新一亿条记录。永远不要使用可能会改变的任何内容作为你的主键。我同意你的第二个陈述。 - HLGEM

0

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

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

是的,这些不是官方货币,但从系统和用户的角度来看,将它们作为货币而不是用户可以购买和出售的附加产品更具灵活性。

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

正式地说,LBP是黎巴嫩镑的ISO标准,所以他们将无法顺利地将黎巴嫩镑添加到系统中。

如果您通过代码识别您的货币,并且将来有一些新的货币被注册为ISO标准(比如LBE或BTC),那么这些货币将与“您”的货币发生冲突。

有人在这里提到,为货币添加额外的int键是一个额外的索引。但是请问,对于300条记录(货币的近似计数),这是一个问题吗?此外,如果您将INT用作货币的主键,则具有其他好处:想象一下一个包含金额和货币的1M个交易的表格,什么更有效:INTS还是CHARS?
所以我会选择INTS。

-2

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

例如,如果英国加入欧元区会怎样?


1
如果在记录财务交易时使用货币代码键,您绝对不会更新该代码。否则,所有历史数据都将被破坏! - ianaré

-2

使用会变化的内容作为主键是一种不好的做法。假设该值发生了变化,那么您就必须更新所有子记录。这样做可能会导致数据库锁定数小时甚至数天。因此,在信息易变的情况下,使用带有自然键唯一索引的整数FK是更好的做法。


1
任何键都可能需要更改(无论是整数还是其他类型)。最安全的策略是假设任何键都可能在某个时候需要更改。相对稳定性是选择键的明智标准,但“不可变性”则不是。 - nvogel
1
这是正确的,但国家代码永远不会改变。如果订单已经发货到某个国家,您将保持该记录不变。即使该国分裂或更改,当时发货的代码是正确的。稍后更改它将使历史数据无效。在某些情况下,这甚至可能是非法的(可能适用数据防护法)。 - ianaré

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接