假设你正在收集有关即将上映的超级英雄电影的内幕信息,你的主要电影表看起来像这样:
表1
Title Director Leading Male Leading Female Villain
--------------------------------------------------------------------------
Green Lantern Kubrick Robert Redford Miley Cyrus Hugh Grant
The Tick Mel Gibson Kevin Sorbo Linda Hunt Anthony Hopkins
这通常可以很好地运行,并且允许非常容易的查询以及行之间的比较。
但是,您希望跟踪每个数据事实的来源,以及发现该事实的记者的姓名。这似乎建议使用类似于EAV表格:
表2
Movie Attribute Value Source Journalist
----------------------------------------------------------------------------------
Green Lantern Director Kubrick CHUD Sarah
Green Lantern Leading Male Robert Redford CHUD James
Green Lantern Leading Female Miley Cyrus Dark Horizons James
Green Lantern Villain Hugh Grant CHUD Sarah
The Tick Director Mel Gibson Yahoo Cameron
...
虽然EAV表格轻松地捕获了我们想要的元数据,但使查询变得更加困难。要获取单个电影的所有基本数据需要更多的工作。具体来说,您必须在这里处理四行内容,以获取绿灯侠的四个重要信��片段;而在表1中,这是一行整齐封装的数据。因此,我的问题是,在我刚才描述的复杂性的背景下,并且因为我知道通常应避免使用EAV表格,EAV是否仍然是最佳解决方案?看起来它似乎是唯一合理的表示此数据的方式。我看到的唯一其他替代方法是结合另一个只包含此类元数据的表1: 表3
Movie Attribute Source Journalist
----------------------------------------------------------------------------------
Green Lantern Director CHUD Sarah
Green Lantern Leading Male CHUD James
Green Lantern Leading Female Dark Horizons James
Green Lantern Villain CHUD Sarah
The Tick Director Yahoo Cameron
...
但这样做非常危险,因为如果有人更改了表1中的列名,比如将“Villain”更改为“Primary Villain”,则表3中的行仍然只会显示“Villain”,因此相关数据将不幸分离。如果“属性”列与另一个表链接,则可以帮助解决此问题,该表作为表1的列的枚举。当然,数据库管理员将负责维护此枚举表以匹配表1的实际列。甚至可能通过使用SQL Server中的系统视图而不是手动创建枚举表来进一步改善情况。虽然我不确定是否可以涉及系统视图的关系。
你有什么建议? EAV是唯一的方法吗?
如果只有一个元数据列(只有“来源”没有“记者”),那怎么办?是否仍然需要采用EAV路线?您可以拥有“导演”、“导演_来源”、“男主角”、“男主角_来源”等列,但这很快变得混乱。是否有一些更好的解决方案我没有想到?
如果我没有澄清任何问题,请在评论中提出,我会根据需要添加更多信息。哦,对了,我使用的电影数据是虚构的:)
编辑:为了简明起见,我想拥有表1的简单性和真正的RDBMS设计,这真正描述了电影条目,同时仍以安全且可访问的方式存储属性的元数据。这可能吗?还是EAV是唯一的方法?
编辑2:在进行了更多网络研究之后,我尚未找到关于EAV的讨论集中在希望在列上存储元数据的愿望的情况。实施EAV的主要原因几乎总是动态和不可预测的列,而这在我的示例中并不是这种情况。在我的示例中,始终存在相同的四个列:导演、男主角、女主角和反派。但是,我想存储每个行的每个列的某些事实(来源和记者)。 EAV会促进这一点,但我想避免采用这种方法。
更新
在保持Table 2设计的情况下,只需将“Movie”列重命名为“Name”,并将整个表称为“Movie”,这里是在SQL Server 2008中执行透视操作以恢复Table 1:
SELECT Name, [Director], [Leading Male], [Leading Female], [Villain]
FROM (Select Name, Attribute, Value FROM Movie) as src
PIVOT
(
Max(Value)
FOR Attribute IN ([Director], [Leading Male], [Leading Female], [Villain])
) AS PivotTable