Database 在DB列中对数据进行编码,但数据本身并不“适合”

Database 在DB列中对数据进行编码,但数据本身并不“适合”,database,normalization,Database,Normalization,我的任务是使一些数据库数据正常化。99%还可以,但我遇到了麻烦 这不是我的问题领域,但类似的问题是书籍。想象一下,你必须记录书籍的细节,以及它们在供应商网站上的表现方式,也许是为了一个价格比较引擎 供应商A、B和C的每本书都由一个数字标识符表示,尽管每个供应商D的数字标识符不同,但是,每一年的版本从1开始,因此您还需要出版年份 如果我只需要处理A、B和C,我就会有一个图书主表,以及一个将我的主图书ID映射到供应商特定ID的查找表。但供应商D破坏了这一点。例如,我不能使vendorID,vendo

我的任务是使一些数据库数据正常化。99%还可以,但我遇到了麻烦

这不是我的问题领域,但类似的问题是书籍。想象一下,你必须记录书籍的细节,以及它们在供应商网站上的表现方式,也许是为了一个价格比较引擎

供应商A、B和C的每本书都由一个数字标识符表示,尽管每个供应商D的数字标识符不同,但是,每一年的版本从1开始,因此您还需要出版年份

如果我只需要处理A、B和C,我就会有一个图书主表,以及一个将我的主图书ID映射到供应商特定ID的查找表。但供应商D破坏了这一点。例如,我不能使vendorID,vendorCode成为唯一的键,因为对于D,vendorcodes可以重用代码1每年都有不同的条目

一个答案是将D的供应商代码作为一个组合变量-因此1232013对于id 123,year=2013,在我的查找代码中有如下内容:

if(vendor = D){
...split the code in two and format the search request accordingly...
}
但它似乎有点…不太好


我是否错过了DB正常化的一些微妙技巧?或者我只需要接受现实世界并不总是以一种好的方式正常化吗?

您的场景类似于数据仓库和遗留系统中常见的情况:映射多个系统的主键。光谱的两端是这样的。显然,供应商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
这种表到目前为止有五个候选键

我们的钥匙 供应商a 供应商 供应商 供应商年、供应商数量 如果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结构

做出选择

如果可行的话,我更喜欢第一种结构。它允许高水平的约束检查。每个列可以而且通常是不同的数据类型,列级约束易于应用和理解。您不必将复合类型硬塞进单个列中,也不必在SELECT语句中解析该列

但是,如果您必须支持数量不确定的供应商,这是不现实的。每个dbms对可以在基表中声明的列数都有硬限制或软限制

但是EAV结构有一些缺点,根据应用程序的不同,这些缺点可能会阻碍显示。例如,保证我们的_键的每个值都映射到第一个结构中每个供应商的一个键是很简单的。在EAV结构中几乎不可能做到这一点


EAV还要求您将复合类型硬塞进单个列中,并在SELECT语句中解析该列。

或者,您也可以只为供应商a、B和C追加一年,然后拆分每个项目。对于A、B和C,您不需要额外的数据。我只是想知道,是否有一种真正的方式不涉及任何形式的笨拙的黑客。