更好的方法来做MySQL对象层

时间:2011-08-22 18:00:09

标签: mysql sql object layer entity-attribute-value

我不是MySQL的专业人士,但想在关系型MySQL表之上做一些类似对象层的事情。

我希望拥有非常多的“结构”,其中包含“bigint”,“longtext”,“datetime”,“double”类型的字段,只存储在7个表格中。

entity_types(et_id,et_name) - “结构”列表;

entity_types_fields(etf_id,parent_et_id,.....,etf_ident,etf_type) - 存储在一个表中的所有结构的结构属性列表; etf_​​type包含int值(0,1,2,3),它引用了下面描述的4个表之一。

实体(e_id,et_id) - 所有可用实体的列表(实体的ID和类型ID)

和4个数据表(包含实体的所有数据) -

entities_props_bigint(parent_e_id,parent_etf_id,ep_data) - 用于BIGINT数据属性 entities_props_longtext(parent_e_id,parent_etf_id,ep_data) - 用于LONGTEXT数据属性 entities_props_datetime(parent_e_id,parent_etf_id,ep_data) - 用于DATETIME数据属性 entities_props_double(parent_e_id,parent_etf_id,ep_data) - 用于DOUBLE数据属性

从这样的数据层进行选择的最佳方法是什么?

让我有e_id(实体的id)列表,每个实体可以有任何类型。我想获得预定义的属性列表。如果某些实体没有这样的属性,我希望它等于NULL。

你有关于如何做的一些信息吗?可能是你有一些联系或已经处理过这类事情。

谢谢!

1 个答案:

答案 0 :(得分:0)

通过在关系数据库之上实现整个元数据系统,您是reinventing the wheel。许多开发人员have tried to do what you're doing然后使用SQL来查询它,就好像它是关系数据一样。但是在SQL中实现非关系数据和元数据系统比你预期的要困难。

我已将问题的relational标记更改为eav,因为您的设计是Entity-Attribute-Value设计的变体。 Stack Overflow中有五个标签的限制。但是你应该知道你的设计不是关系型的。

关系设计必须为实体的所有实例提供一组固定的属性。在关系数据库中表示它的正确方法是使用表的列。这允许您为每个属性提供名称数据类型,并确保同一组名称及其数据类型适用于表的每一行。

  

从这样的数据层进行选择的最佳方法是什么?

查询设计的唯一可扩展方法是将属性数据和元数据作为行获取,然后在应用程序代码中重构对象。

SELECT e.e_id, f.etf_ident, f.etf_type, 
    p0.ep_data AS data0, 
    p1.ep_data AS data1, 
    p2.ep_data AS data2,
    p3.ep_data AS data3
FROM entities AS e
INNER JOIN entity_type_fields AS f ON e.et_id = f.parent_et_id
LEFT OUTER JOIN entities_props_bigint   AS p0 ON (p0.parent_e_id,p0.parent_etf_id) = (e.e_id,f.etf_id) 
LEFT OUTER JOIN entities_props_longtext AS p1 ON (p1.parent_e_id,p1.parent_etf_id) = (e.e_id,f.etf_id) 
LEFT OUTER JOIN entities_props_datetime AS p2 ON (p2.parent_e_id,p2.parent_etf_id) = (e.e_id,f.etf_id) 
LEFT OUTER JOIN entities_props_double   AS p3 ON (p3.parent_e_id,p3.parent_etf_id) = (e.e_id,f.etf_id) 

在上面的查询中,每个实体字段最多应匹配一个属性,其他数据列将为null。如果所有四个数据列都为null,则缺少实体字段。


重新评论,好吧,现在我更了解你要做的事情。您在树中有一组实体实例,但每个实例可能是不同的类型。

以下是我的设计方法:

  • 将所有实体子类型的所有属性存储在某种超类型表中。

    实体(e_id,entity_type,name,date_created,creator,sku等)

  • 将特定于实体子类型的任何属性存储在自己的表中,如Martin Fowler的Class Table Inheritance设计。

    entity_books(e_id,isbn,pages,publisher,volumes等)

    entity_videos(e_id,格式,地区,光盘等)

    entity_socks(e_id,fabric,size,color等)

  • 使用Closure Table设计来建模对象的层次结构。

    entity_paths(ancestor_e_id,descendant_e_id,path_length)

有关类表继承和关闭表的更多信息,请参阅我的演示文稿Practical Object-Oriented Models in SQLModels for Hierarchical Data in SQL,或我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming或Martin Fowler的书Patterns of Enterprise Application Architecture