1

我的任务是规范化一些数据库数据。99% 都很好,但我遇到了难题。

它不是我的问题领域,但类似的领域是书籍。想象一下,您必须记录书籍的详细信息,以及它们在供应商网站上的表现方式(可能是为了价格比较引擎)

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

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

一个答案是使 D 的供应商代码成为一个组合变量 - 因此 id 123 的“123,2013”​​,年份 = 2013,并且在我的查找代码中具有如下内容:

if(vendor = D){
...split the code in two and format the search request accordingly...
}

但它似乎有点...... hacky。

我是否错过了一些数据库规范化的微妙技巧?还是我只需要接受现实世界并不总是以一种好的方式正常化?

4

1 回答 1

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

这种表(到目前为止)有五个候选键。

  • 我们的密钥
  • 供应商_a
  • 供应商_b
  • 供应商_c
  • vendor_d_yr, vendor_d_num

如果您的 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 结构有一些缺点,这些缺点可能会让人大吃一惊,这取决于您的应用程序。例如,保证“our_key”的每个值都映射到第一个结构中每个供应商的键是微不足道的。在 EAV 结构中几乎不可能做到这一点。

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

于 2013-05-29T23:04:53.547 回答