由于此时可能没有其他正当理由,我们总是这样做,“如何构建新系统以使用用于表示州代码的参考数据?
例如,一个案例可能有2个有效状态,'打开'或者'关闭'。从历史上看,我已经看到许多系统将这些有效值存储在包含此参考数据的数据库表中,并称为代码类型(' CaseStatus'),并且每个有效值都有一个& #39;代码'值(例如' OPN')以及需要向用户显示值时使用的解码或显示值(在这种情况下'打开')。
如果今天开发基于Java的系统,从类型安全的代码角度来看,我们会定义一个这样的枚举:
public enum CaseStatus{
Open("OPN"),
Closed("CLS");
private String codeValue;
private CaseStatus(String codeValue){
this.codeValue = codeValue;
}
}
仅从源代码的角度来看,这很好,Enum使用有限值的受限列表强制执行类型安全,但是它本身并不表示此代码类型或它的有效值。数据库。如果有数据用户直接针对数据库运行adhoc报告,他们需要一种方法来查找“OPN' CLS'”的解码值。从历史上看,这可以使用包含代码类型,代码及其解码值的参考表来完成。
我们继续将这些状态代码值用作' 3字母代码'似乎很奇怪,此时此刻的动机不再是因为我们需要在数据库中节省空间(' OPN' vs' Open'无论如何都不是一个很好的优化。)
人们在最近使用过的系统上使用或看到了哪些其他方法?您是仅在数据库中维护参考数据,仅在代码中还是在两个地方维护参考数据,如果您同时维护参考数据,您使用什么方法来保持两者同步?
答案 0 :(得分:1)
我遇到的一个解决方案是使用数据库中的物化视图来动态重新计算非规范化关系。在基于文档的数据库中,您可能会将CaseStatus
存储为String
。最后,您可以使用ORM工具将CaseStatus
存储为Object
,但在我熟悉参考数据的情况下,存储在数据库中(如果您将其存储在代码中,那么它需要构建和部署到生产,以及发布的其他测试。
答案 1 :(得分:1)
首先,如果只有两个可能的值,并且不可能期望它们发展成更大的数字(如open
/ closed
的例子),我可能会定义status_open
列BOOLEAN
或SMALLINT
(0/1)或CHAR
(Y / N)。
当状态的宇宙更大(或可能增加到两个以上的值)时,我会使用代理键。虽然保存几个字节几乎不是优化,但索引和加入CHAR
值列比索引和加入INTEGER
列更昂贵。虽然我对INTEGER
vs CHAR(3)
的问题没有指标,但我认为对于这种情况,差异不会像INTEGER与CHAR(50)那样大。 )。
然而,我在小CHAR缩写中发现的一个缺点是,有时很难找到有意义的值。假设您的状态为"已损坏 - 已订购更换" ,如果我将其称为“#34; BRO&#34 ;?是否比调用3
更好?
另一方面,即使模型不需要,我发现在VARCHAR
上添加一个简短的status
列也很方便,用于描述每个助记符或代理键的含义。 (模型增长后,很难记住所有模型!)
我的实施(在特定情况下有适当的例外情况)可能是:
在Java端,枚举,就像你定义的那样。 (即使对于类似布尔值的值,有时它有助于为每个值设置不同的枚举,特别是如果有方法将这些值中的多个作为参数。具有相同类型的长参数列表的方法是灾难的处方)。 / p>
在SQL端:
CREATE TABLE status (
id INTEGER PRIMARY KEY,
description VARCHAR(40)
)
CREATE TABLE entity (
...
status_id INTEGER REFERENCES status(id)
)
INSERT INTO status VALUES (0,'Closed');
INSERT INTO status VALUES (1,'Open');
INSERT INTO status VALUES (2,'Broken - replacement has been ordered');