sql – 如何设计数据库模式以支持类别标记?

前端之家收集整理的这篇文章主要介绍了sql – 如何设计数据库模式以支持类别标记?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图像 Database Design for Tagging这样的东西,除了我的每个标签被分组.

例如,假设我有一个关于车辆的数据库.假设我们实际上不太了解车辆,所以我们不能指定所有车辆的列.因此,我们将“标记”车辆信息.

1. manufacture: Mercedes
   model: SLK32 AMG
   convertible: hardtop

2. manufacture: Ford
   model: GT90
   production phase: prototype

3. manufacture: Mazda
   model: MX-5
   convertible: softtop

现在,你可以看到所有的汽车都被标记了他们的制造和型号,但其他类别并不是全部匹配.请注意,一辆汽车只能有一个类别. IE浏览器.一辆汽车只能有一个制造商.

我想设计一个数据库支持所有梅赛德斯的搜索,或者能够列出所有的制造商.

我目前的设计是这样的:

vehicles
  int vid
  String vin

vehicleTags
  int vid
  int tid

tags
  int tid
  String tag
  int cid

categories
  int cid
  String category

我拥有所有正确的主键和外键,除了我不能处理每个车只能有一个制造商的情况.还是我可以

我可以在vehicleTags中的复合主键中添加外键约束吗? IE浏览器.我可以添加一个约束,使得复合主键(vid,tid)只能在车辆标签中没有一行,才能添加到车辆标签,以便对于同一个vid,没有一个tid同样的cid?

我的猜测是否定的我认为这个问题的解决方案是添加一个cid列到vehicleTags,并使新的复合主键(vid,cid).它看起来像:

vehicleTags
  int vid
  int cid
  int tid

这样可以防止汽车有两个制造商,但现在我已经复制了cid中的信息.

我的模式应该是什么?

在我之前的问题How do you do many to many table outer joins?中,Tom注意到我的数据库模式中的这个问题

编辑
我知道,在这个例子中,制造业应该是车载表中的一列,但是我们说你不能这样做.这个例子只是一个例子.

解决方法

这是 Entity-Attribute-Value设计的另一个变化.

更可识别的EAV表格如下所示:

CREATE TABLE vehicleEAV (
  vid        INTEGER,attr_name  VARCHAR(20),attr_value VARCHAR(100),PRIMARY KEY (vid,attr_name),FOREIGN KEY (vid) REFERENCES vehicles (vid)
);

有些人强制attr_name引用预定义属性名称的查找表,以限制混乱.

您所做的只是简单地将一个EAV表传播到三个表上,但不改进元数据的顺序:

CREATE TABLE vehicleTag (
  vid         INTEGER,cid         INTEGER,tid         INTEGER,cid),FOREIGN KEY (vid) REFERENCES vehicles(vid),FOREIGN KEY (cid) REFERENCES categories(cid),FOREIGN KEY (tid) REFERENCES tags(tid)
);

CREATE TABLE categories (
  cid        INTEGER PRIMARY KEY,category   VARCHAR(20) -- "attr_name"
);

CREATE TABLE tags (
  tid        INTEGER PRIMARY KEY,tag        VARCHAR(100) -- "attr_value"
);

如果您要使用EAV设计,您只需要车辆标签和类别表.

CREATE TABLE vehicleTag (
  vid         INTEGER,-- reference to "attr_name" lookup table
  tag         VARCHAR(100,-- "attr_value"
  PRIMARY KEY (vid,FOREIGN KEY (cid) REFERENCES categories(cid)
);

但请记住,您正在将数据与元数据进行混合.您无法对数据模型应用某些限制.

>如何使其中一个类别成为强制性(常规列使用NOT NULL约束)?
>如何使用sql数据类型验证一些标签值?您不能,因为您为每个标签值使用长字符串.这个字符串对于您将来需要的每个标签都足够长吗?你不能告诉
>如何将一些标签限制为一组允许的值(传统的表使用查找表的外键)?这是你的“软顶”与“软顶”的例子.但是,您不能对标签列做出约束,因为该约束将适用于其他类别的所有其他标记值.您可以有效地将发动机尺寸和油漆颜色限制为“软顶”.

sql数据库与此模型不兼容.得到正确的是非常困难的,查询它变得非常复杂.如果您继续使用sql,那么您将更好地对表进行常规建模,每个属性有一列.如果您需要“子类型”,然后根据子类型(Class-Table Inheritance)定义下属表,否则使用Single-Table Inheritance.如果每个实体的属性有无限变化,则使用Serialized LOB.

为这些流体,非关系数据模型设计的另一种技术是语义数据库,存储数据于RDF,并与SPARQL进行了查询.一个免费的解决方案是Sesame.

猜你在找的MsSQL相关文章