我的任务是规范化一些数据库数据。 99%的情况很好,但我已经打了一个quardry。
它不是我的问题领域,但类似的是书籍。想象一下,您必须记录书籍的详细信息,以及它们如何在供应商网站上展示(可能是价格比较引擎)
供应商A,B和C的每本书都由一个数字标识符表示(虽然每个供应商都不同)但是,供应商D每年的发布时间为1,因此您还需要发布年份。
如果我只需要处理A,B和C,我就会有一个主表书,以及一个将我的主书ID映射到供应商特定ID的查找表。但供应商D打破了这一点。例如,我不能使vendorID,vendorCode成为唯一的密钥,因为对于D,供应商代码可以重复使用(代码1每年将有不同的条目....)
一个答案是让D的供应商代码成为一个组合变量 - 所以“123,2013”代表id 123,年份= 2013,并且在我的查找代码中有类似的内容:
if(vendor = D){
...split the code in two and format the search request accordingly...
}
但似乎有点......哈基。
我是否错过了DB规范化的一些微妙技巧?或者我只是需要接受现实世界并不总是以一种很好的方式正常化?
答案 0 :(得分:0)
您的场景类似于数据仓库和旧系统中常见的场景:映射来自多个系统的主键。光谱的两端看起来像这样。 (很明显,供应商D的真实密钥必须包括年份。)
One end of the spectrum
our_key vendor_a vendor_b vendor_c vendor_d_yr vendor_d_num
--
1001 32 43 1856 2013 1
1002 143 887 2924 2013 2
那种表(到目前为止)有五个候选键。
如果您的dbms支持复合的,用户定义的类型,则可以使用供应商“D”的复合类型。
The other end of the spectrum
our_key vendor vendor_key
--
1001 A 32
1001 B 43
1001 C 1856
1001 D 2013-1
1002 A 143
1002 B 887
1002 C 2924
1002 D 2013-2
此表有一个候选键:{our_key,vendor,vendor_key}。频谱的这一端基本上是EAV结构。
做出选择
如果实用,我更喜欢第一种结构。它允许高级别的约束检查。每列可以(通常是)不同的数据类型,列级约束易于应用和理解。您不必将shoehorn复合类型放入单个列中,也不必在SELECT语句中解析该列。
但是,如果必须支持不确定数量的供应商,那么这是不切实际的。每个dbms都对您可以在基表中声明的列数有硬限制或软限制。
但是EAV结构有一些缺点,可能是显示停止,取决于您的应用程序。例如,保证“our_key”的每个值都映射到第一个结构中每个供应商的密钥都是微不足道的。在EAV结构中几乎不可能做到这一点。
EAV还要求您将复合类型解压缩到一个列中,并在SELECT语句中解析该列。