SQL反模式:实体-属性-值(EAV)问题(二)

在上一篇文章中,介绍了EAV模式存在的问题,文章链接如下:

https://blog.youkuaiyun.com/dh858115/article/details/104203110

那么针对EAV的问题有什么解决方案呢?

解决方案1.单表法

   将所有的属性编程列的方式存储起来,这样可以通过列的类型限制不合法的数据,如创建以下表

CREATE TABLE Issues1 (
issue_id int PRIMARY KEY,
reported_by BIGINT NOT NULL,
product_id BIGINT,
priority VARCHAR(20),
version_resolved VARCHAR(20),
status VARCHAR(20),
issue_type VARCHAR(10), -- BUG or FEATURE
severity VARCHAR(20), -- only for bugs
version_affected VARCHAR(20), -- only for bugs
sponsor VARCHAR(50), -- only for feature requests
);

Issue1表分别存储了bug和feature两种类型,部分列进适用于bug或者feature,通过Issue_type来区分。

解决方案2.混合表

方案1中存在不同类型使用不同列,这样的设计有时候看起来不是很好,那么可以将他们拆分成2个表,具体如下:

CREATE TABLE Bugs (
issue_id int PRIMARY KEY,
reported_by BIGINT NOT NULL,
product_id BIGINT ,
priority VARCHAR(20),
version_resolved VARCHAR(20),
status VARCHAR(20),
severity VARCHAR(20), -- only for bugs
version_affected VARCHAR(20) -- only for bugs
);
CREATE TABLE FeatureRequests (
issue_id int PRIMARY KEY,
reported_by BIGINT NOT NULL,
product_id BIGINT ,
priority VARCHAR(20),
version_resolved VARCHAR(20),
status VARCHAR(20),
sponsor VARCHAR(50) -- only for feature requests
);

上面拆分成2个表的好处在于,不会将属于bug列的内容不小心插入到feature所属的列。而且不需要维护Issue_type列,以区分bug或者feature。但是如果想查询bug和feature时,就需要使用union来联合结果了。

解决方案3.继承表

为了解决上面使用union来做组合查询的问题,我们可以设计一个issue表,然后bug和feature继承自issue,具体SQL如下:

CREATE TABLE Issues (
issue_id int PRIMARY KEY,
reported_by BIGINT NOT NULL,
product_id BIGINT,
priority VARCHAR(20),
version_resolved VARCHAR(20),
status VARCHAR(20)
);
CREATE TABLE Bugs (
issue_id BIGINT PRIMARY KEY,
severity VARCHAR(20),
version_affected VARCHAR(20)
);
CREATE TABLE FeatureRequests (
issue_id BIGINT PRIMARY KEY,
sponsor VARCHAR(50)
);

通过issue_id可以关联到父类或者子类,这时,如果需要查询bug和feature,只要使用如下语句即可,比union优雅

SELECT i.*, b.*, f.*
FROM Issues AS i
LEFT OUTER JOIN Bugs AS b on i.issue_id = b.issue_id
LEFT OUTER JOIN FeatureRequests AS f on i.issue_id = f.issue_id

解决方案4.半结构化数据

如果在你的设计中,需要很多动态的attribute,那么建议你使用xml,JSON或者大对象等格式,这些数据格式允许你做动态的扩展,同时其他列的数据校验依然有效,同时兼具灵活扩展性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值