Pyr*_*cal 15 sql tags schema foreign-keys entity-attribute-value
我正在尝试像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
Run Code Online (Sandbox Code Playgroud)
现在您可以看到所有汽车都标有其制造和型号,但其他类别并不完全匹配.请注意,汽车只能拥有每个类别中的一个.IE浏览器.一辆汽车只能有一个制造商.
我想设计一个数据库来支持搜索所有梅赛德斯,或者能够列出所有制造商.
我目前的设计是这样的:
vehicles
int vid
String vin
vehicleTags
int vid
int tid
tags
int tid
String tag
int cid
categories
int cid
String category
Run Code Online (Sandbox Code Playgroud)
我有所有正确的主键和外键,除了我无法处理每辆车只能有一个制造商的情况.或者我可以吗?
我可以在vehicleTags中为复合主键添加外键约束吗?IE浏览器.我是否可以添加一个约束,使得复合主键(vid,tid)只能在vehicleTags中没有行时才添加到vehicleTags,这样对于同一个vid,还没有一个tid在同样的cid?
我的猜测是否定的.我认为这个问题的解决方案是向vehicleTags添加一个cid列,并创建新的复合主键(vid,cid).它看起来像:
vehicleTags
int vid
int cid
int tid
Run Code Online (Sandbox Code Playgroud)
这可以防止汽车有两个制造商,但现在我已经复制了tid在cid中的信息.
我的架构应该是什么?
在我之前的问题中,Tom在我的数据库模式中发现了这个问题,你如何做多对多表外连接?
编辑
我知道在示例制造中应该真的是车辆表中的一列,但是假设你不能这样做.这个例子只是一个例子.
Bil*_*win 15
这是实体 - 属性 - 值设计的另一个变体.
更易识别的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)
);
Run Code Online (Sandbox Code Playgroud)
有些人强制attr_name引用预定义属性名称的查找表,以限制混乱.
您所做的只是将EAV表分布在三个表上,但不改进元数据的顺序:
CREATE TABLE vehicleTag (
vid INTEGER,
cid INTEGER,
tid INTEGER,
PRIMARY KEY (vid, 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"
);
Run Code Online (Sandbox Code Playgroud)
如果你打算使用EAV设计,你只需要vehicleTags和categories表.
CREATE TABLE vehicleTag (
vid INTEGER,
cid INTEGER, -- reference to "attr_name" lookup table
tag VARCHAR(100, -- "attr_value"
PRIMARY KEY (vid, cid),
FOREIGN KEY (vid) REFERENCES vehicles(vid),
FOREIGN KEY (cid) REFERENCES categories(cid)
);
Run Code Online (Sandbox Code Playgroud)
但请记住,您正在将数据与元数据混合在一起.您将无法将某些约束应用于数据模型.
NOT NULL约束)? tag列进行约束,因为该约束将适用于其他类别的所有其他标记值.您可以有效地将发动机尺寸和油漆颜色限制为"软顶".SQL数据库不适用于此模型.要做到正确是非常困难的,并且查询它变得非常复杂.如果继续使用SQL,则最好按常规方式对表进行建模,每个属性只有一列.如果您需要"子类型",则为每个子类型定义一个从属表(Class-Table Inheritance),否则使用Single-Table Inheritance.如果每个实体的属性具有无限的变化,则使用序列化LOB.
为这些流体非关系数据模型设计的另一种技术是语义数据库,它将数据存储在RDF中并使用SPARQL进行查询.一个免费的解决方案是芝麻.