我负责内置遗留数据库的遗留系统。 它以一种奇怪的方式为数据建模,例如看一下这个通用表:
nr jdptype jdpid jdpdescr
----------- ---------- ----------- --------------------------------------------------
1 jrelation 1 Leverancier
2 jrelation 2 Klant
3 jrelation 3 Dealer
4 jcontact 1 Contact
5 jaddress 1 Hoofdadres
6 jcomm 1 Phone
7 jcomm 2 Fax
8 jcomm 3 Email
9 jcomm 4 Internet
10 jcomm 5 Mobile
11 jfunction 2 Eigenaar
13 jfunction 4 Medewerker
14 jfunction 5 Ontwerper
15 jcountry 2 België
16 jcountry 3 Duitsland
17 jcountry 4 Nederland
18 jcountry 5 Engeland
19 jcountry 6 Frankrijk
20 jfunction 1 Ontw. Verk.
21 jlanguage 2 Nederlands
35 jtitle 2 Juff.
36 jaddress 4 Leveradres
38 jtitle 3 Dhr
39 jcountry 7 China
41 jaddress 5 Filiaal
42 jrelation 4 Architect
43 jrelation 5 Aannemer
44 jlanguage 3 Frans
45 jlanguage 4 Duits
46 jfiliaal 2 FrWe
47 jfiliaal 3 FrZo
48 jfiliaal 4 BoTu
49 jtitle 4 Prof
50 jtitle 5 Prof.
52 jtitle 7 Ing.
53 jtitle 8 Mr.
54 jtitle 9 Mevr.
55 jtitle 10 Dhr. Ing.
56 jtitle 11 Dhr. Ir.
57 jtitle 12 Mevr. Ing.
58 jtitle 13 Mevr. Ir
59 jtitle 14 Dhr. & Mevr.
60 jtitle 15 M. et Mme.
61 jtitle 16 Mlle
62 jtitle 17 Mme.
64 jrepres 3 J. Van Genechten
70 jrepres 9 R. Verschueren
75 jrepres 14 D. Verschueren
77 jrepres 15 Geen
78 jfunction 6 Verkoper
79 jfunction 7 Medew. Verk.
80 jfunction 8 Vertegenwoordiger
82 jrepres 17 S. Van Onckelen
83 jrepres 18 L. Jacobs
84 jrepres 19 R. Schoeters
85 jrepres 20 L. Delen
86 jrepres 21 B. Bouvé
87 jrepres 22 P. Van Haute
88 jfiliaal 1 MeMe
89 jrepres 16 E. Heykants
90 jfiliaal 5 Arro
91 jfiliaal 6 OfZo
nr是主键,但实际上对我来说,这看起来像是几个被抛在一起的表。 我的直觉是创建一个关系类型表,一个通信类型表,一个国家表等等。
它违反了当前状态下的规范化规则,因为jpddescr与nr无关,而是与jdptype和jdpid的组合有关。
我的假设是否正确,我是否应该考虑将其重构为正确的设计,或者是否有任何我想要的东西支持这种“通用”设计?
我在尝试创建实体图时偶然发现了这一点。真的很烦人,不得不为这个表创建导航属性,比如一个关系,没有什么可以阻止你填写函数的id。
答案 0 :(得分:1)
看起来确实很奇怪,但正确的修复需要更深入了解用例。
我认为创建许多表有其自身的缺点,特别是在这种情况下不会是一对一的替换,因为当前的实现在可能的类型方面是灵活的(其无限的对比)一组常数表。)
我会用链接到jdptype
表的外键替换jdptypes
,以改善设计和性能。
答案 1 :(得分:1)
作为一个域,它实际上是一个sum类型/标记联盟,也就是One True Lookup Table。希望在(jdptype,jdpid)上至少声明一个唯一约束。您正确地指出它包含传递依赖性,因此存在更新异常的风险。但是,我不太关心这一点,更关心的是,任何读取与此表相关的数据的代码都不知道预期的域名。如果我查询,我会获得地址,标题,国家,语言,电话号码或其他内容吗?它可能是一个混合,因此我必须根据具体情况处理每一行,而不是一次处理整个集合。它也可能在代码中普遍存在,因为每个模块的查找表都可能卷入这个,因此案例逻辑将在许多地方重复。而且,对于特定类型的值,为数据库添加新属性有点困难,例如电话号码的国际拨号代码或国家的ISO 2位代码或邻居。想要构建一个由关键字和语言键入的本地化表吗?请注意,您的翻译可能取决于电话号码而不是语言。克服许多这些问题的最简单方法是开始为每种类型添加新表,这违背了将其全部放在一个表中的最初目的。其他人可以通过检查约束来克服,如果他们得到DBMS的支持,这将比等效的外键约束更复杂,效率更低。
要重构它,我会为每个类型的行子集创建一个视图,可能会与任何一对一映射到这些行的其他表连接。然后按照我的方式通过系统重写对基表的任何引用。然后,我可以分解基表并用单独的表替换视图,最后创建必要的外键约束来强制引用完整性。但是,在开始任何重构之前,我建议您检查现有数据,以验证您对数据正确性的假设实际上是否成立。通常,任何可记录的内容都将被记录下来。