我使用国家代码作为主键,例如“AU、US、UK、FR”等,在我的国家表中。
我使用货币代码作为主键,例如“AUD、GBP、USD”等,在我的货币表中。
我认为我的做法没问题,但另一位开发人员要求我将所有主键都改成整数,因为他说国家代码和货币代码未来可能会更改。我们并不知道这一点,但在这种情况下,他是正确的,他的方法是最安全的。
我应该将主键改为整数以确保安全吗?还是可以保持原样?
我使用国家代码作为主键,例如“AU、US、UK、FR”等,在我的国家表中。
我使用货币代码作为主键,例如“AUD、GBP、USD”等,在我的货币表中。
我认为我的做法没问题,但另一位开发人员要求我将所有主键都改成整数,因为他说国家代码和货币代码未来可能会更改。我们并不知道这一点,但在这种情况下,他是正确的,他的方法是最安全的。
我应该将主键改为整数以确保安全吗?还是可以保持原样?
我会使用带有字符列的ISO代码。
如果一个国家分裂了,你将得到新的ISO代码(比如SC、WL、EN),但对于历史数据,英国仍然是有效的。
货币也是一样的。2000年的交易将使用当时的货币:法国法郎、德国马克、比利时香蕉,但不会使用欧元。
INT
也需要这样做。在这种情况下,我认为人造代理键(如INT
)只会增加开销,而不真正有助于保持事物更容易/更明确。CHAR(3)
或CHAR(5)
- 没有必要为这么短的字符串使用VARCHAR
,而且,可变长度字段(如VARCHAR)的行为与定长字段(如INT
或CHAR
)非常不同(在性能方面并不“更好”)。从逻辑角度来看,添加代理键会增加列、附加键约束和更复杂的数据查询和操作逻辑。这是需要考虑的一点。
从物理角度来看,在SQL Server中,整数型的主键所占用的空间是CHAR(2)或CHAR(3)的两倍以上。这意味着引用表和索引将变得更大。它还使得对那些外键值进行任何更新都变得更加昂贵。我不知道您的数据情况,但引用那些外键列中的数据可能比父表中的国家代码和货币代码值更新得更频繁。相比之下,货币和国家的ISO代码几乎永远不会更改,因此可能不必太担心。通过更改为整数型主键,您很可能会增加更新那些外键值的成本。
如果您正在考虑将其作为性能优化而进行这样的更改,则建议您非常仔细地评估INTEGER主键是否会使这些值的更新成本更高或更低。我建议您忽略那些说“总是要做X”的人。教条在数据库设计中没有帮助。评估实践中的真正影响,并根据此进行决策。
ON UPDATE CASCADE
,那么这些代码改变谁会在意呢?如果您决定转移到INT代理,仍然请记得在这些列上放置唯一约束 - 它们是这些表的真正关键。
我会使用INT ids作为关键字,而不是ISO代码,并解释原因:
我曾经工作的组织使用“自有货币”(LBP)-例如,当用户执行某些交易时,他会获得一定数量的LBP作为奖励。此外,他可以将这些LBPs兑换成美元、欧元等,反之亦然,用LBPs支付服务等。此外,我在ISO标准中没有找到比特币(Bitcoin)货币。
是的,这些不是官方货币,但从系统和用户的角度来看,将它们作为货币而不是用户可以购买和出售的附加产品更具灵活性。
我曾经工作的组织不使用INTS作为主键,他们使用ISO代码作为ID(加上那些额外的货币)。
正式地说,LBP是黎巴嫩镑的ISO标准,所以他们将无法顺利地将黎巴嫩镑添加到系统中。
如果您通过代码识别您的货币,并且将来有一些新的货币被注册为ISO标准(比如LBE或BTC),那么这些货币将与“您”的货币发生冲突。
有人在这里提到,为货币添加额外的int键是一个额外的索引。但是请问,对于300条记录(货币的近似计数),这是一个问题吗?此外,如果您将INT用作货币的主键,则具有其他好处:想象一下一个包含金额和货币的1M个交易的表格,什么更有效:INTS还是CHARS?是的,在为时已晚之前,将其更改为整数键是一个好主意。
例如,如果英国加入欧元区会怎样?
使用会变化的内容作为主键是一种不好的做法。假设该值发生了变化,那么您就必须更新所有子记录。这样做可能会导致数据库锁定数小时甚至数天。因此,在信息易变的情况下,使用带有自然键唯一索引的整数FK是更好的做法。
INT
类型 - 但如果您保持原样,建议使用CHAR(3)
(不是 VARCHAR!) 来存储这些代码。 - marc_s