Database design 对枚举而不是int使用短字符串的缺点?

Database design 对枚举而不是int使用短字符串的缺点?,database-design,schema,Database Design,Schema,我的数据库中有许多类似枚举的字段。只是一个整数,它是另一个表的FK,该表可能包含一个显示名称或一点附加数据。问题是,这个数字毫无意义,在代码中使用起来也不是很好。此外,如果您试图合并来自不同数据库的某些枚举,或者移动数据,或者如果是自动增量,则可能会遇到名称/键冲突 使用短字符串有什么缺点吗?有点像常数?用它作为主键?一个int通常是4字节,我想我真的不需要超过10个字符,所以一个varchar(10)就可以了。。。我不怀疑磁盘使用会成为一个问题。我个人的做法是对需要更改代码才能添加或删除的项目

我的数据库中有许多类似枚举的字段。只是一个整数,它是另一个表的FK,该表可能包含一个显示名称或一点附加数据。问题是,这个数字毫无意义,在代码中使用起来也不是很好。此外,如果您试图合并来自不同数据库的某些枚举,或者移动数据,或者如果是自动增量,则可能会遇到名称/键冲突


使用短字符串有什么缺点吗?有点像常数?用它作为主键?一个int通常是4字节,我想我真的不需要超过10个字符,所以一个varchar(10)就可以了。。。我不怀疑磁盘使用会成为一个问题。

我个人的做法是对需要更改代码才能添加或删除的项目使用文本键。如果给定的项目是用户应该能够添加或删除的,那么我将坚持使用代理键。这允许您的代码使用更易于阅读的文本值。例如,“状态”(例如开/关、收购/待决/出售)。根据不同的状态,总会有不同的代码,因此,该代码需要查找特定的状态值。这些“状态”不是任何人都可以简单地添加、删除甚至重命名的。代码依赖于它们。因此,对于这些,我使用字符串PK。但是,用户应该能够随意添加或删除“类别”,在这种情况下,代理密钥(与适当的业务密钥组合)更好。

这取决于密钥的不可变程度

例如,如果我们谈论的是使用邮政编码作为键链接到美国各州表,那么这没有什么害处。例如,任何人都不太可能将加利福尼亚州的邮政编码从CA更改为其他内容,因此将其存储为密钥是完全合理的


另一方面,订单状态代码之类的东西可能会随着时间的推移而改变。当您第一次构建应用程序时,您可能有一些状态(即“已获取”、“已装运”、“已完成”)。但是,随着时间的推移,业务部门可能会决定需要添加新的状态,并且需要修改现有的状态——例如,他们可能希望采用“已装运”状态,并将其分解为“已装运”、“在途”和“现有”状态。如果发生这种情况,并且您依赖于“Shipped”作为键,那么您将对
Order
表中具有“Shipped”键的所有行进行一系列更新,否则您将得到一系列具有较低意义键的订单。另一方面,如果使用无意义的数字键,则只需更新
Order\u Status
表即可插入新值并更新“Shipped”行。

在这种情况下,您可以定义“business key”吗?另外,如果有一个categories表和一个userCategories表将用户和类别作为一个自然PK连接起来,这不是更“自然”吗?@Kevin Peno-RE:Business Key。根据定义,代理密钥是任意的。标识/自动编号列没有继承含义。表上必须有其他强制唯一性的约束。例如,如果您有一个类别表,其中有一个名称列和一个自动编号列,那么没有什么可以阻止某人添加仅由任意值区分的重复类别。业务密钥是用户用来区分一行和另一行的。@Thomas,我明白了。我只是想确定我们在同一页上。给出你的答案,我的第二个问题的答案不是“是”吗(在大多数情况下)?@Kevin Peno-RE:Categories-类别的确切模式并不重要,重要的是你希望允许用户随意创建类别,而不是代码依赖的值。您永远不会想硬编码特定类别的使用,因为您必须假设这些类别可能会改变。但是,管道过程中的状态可能具有非常特定的行为,因此您不希望允许用户临时创建它们。@Kevin Peno-Correct。varchar(10)和int在我看来是微不足道的。最重要的是代码的清晰性和数据的一致性。在你们的例子中,你们不会有混乱吗?将密钥拆分为3会导致其自身的问题。假设这只是一个重命名问题,那不是
FK
s的作用吗?而且,如果一个密钥失效(例如,
Shipped
对于
onplallet
InTransit
,&
InCustoms
),这不意味着您实际上需要一个活动/非活动字段吗?正如我对Thomas所说的,我只是想理解你的答案,因为我对这个主题和OP一样好奇。@Kevin-外键可以确保如果你在
Order
表中有一个值“Shipped”,那么
Order\u Status
表中就有一个相关行。当密钥被拆分时,需要有人决定如何处理现有订单(即,现有的“已发货”订单应转到“内部处理”)。如果你有无意义的密钥,那就是1个更新和2个插入到
Order\u Status
。但是,如果您有有有意义的键,那么您可能会得到大量具有“已发货”状态的
订单
行,用户现在必须知道这些行映射到“内部”,或者您最终会更新
订单
@Kevin中的大量行(续)-我看到过这样的情况:人们使用像这样有意义的键最终导致整个业务部门使用3个系统之前的状态命名法,因为他们依赖于状态,而不是查看
Order\u status
表中的新名称,这在映射不明显时造成了无尽的悲痛。由于不同的项目最终的映射略有不同,这导致了大量重复/浪费的工作。@Justin:我想我只是不完全理解更新是如何/为什么不好?我想到了让斯图来的全部理由