如何在数据库中表示实体的许多类似属性?

时间:2012-11-16 22:47:24

标签: sql database postgresql database-design entity-attribute-value

假设我正在建立一个关于汽车的网站。汽车实体有许多类似枚举的属性:

  • 传输(手动/自动)
  • 燃料(汽油/柴油/生物乙醇/电动)
  • 车身风格(轿跑/轿车/敞篷车/ ......)
  • 空调(无/简单/双区)
  • 外观颜色(黑/白/灰/蓝/绿/ ......)
  • 内饰颜色(黑/白/灰/蓝/绿/ ......)

这些属性的列表将来可能会发生变化。在数据库中对它们进行建模的最佳方法是什么?我可以想到以下选项,但无法真正决定:

  • 使用枚举值在car表中使用字段
    • 以后很难添加更多列,可能是最快的
  • 使用car表中的引用查找表的外键字段
    • 以后很难添加更多的colums,有点慢
  • 为存储可能值的每个属性创建单独的表,并为存储car和属性值之间的连接创建另一个表
    • 以后容易添加更多可能的值,甚至更慢,似乎太复杂了

6 个答案:

答案 0 :(得分:1)

Idealy是创建一个关系数据库。 DB中的每个表都应该由一个类表示,就像在hibernate中一样。你应该为汽车制作2张桌子。一个用于内饰,一个用于汽车外部。如果您想添加额外的功能,只需添加更多列。

答案 1 :(得分:1)

现在这是一个(非常基本的)EAV模型:

DROP TABLE IF EXISTS example.zvalue CASCADE;
CREATE TABLE example.zvalue
        ( val_id SERIAL NOT NULL PRIMARY KEY
        , zvalue varchar NOT NULL
        , CONSTRAINT zval_alt UNIQUE (zvalue)
        );
GRANT SELECT ON TABLE example.zvalue TO PUBLIC;

DROP TABLE IF EXISTS example.tabcol CASCADE;
CREATE TABLE example.tabcol
        ( tabcol_id SERIAL NOT NULL PRIMARY KEY
        , tab_id BIGINT NOT NULL REFERENCES example.zname(nam_id)
        , col_id BIGINT NOT NULL REFERENCES example.zname(nam_id)
        , type_id varchar NOT NULL
        , CONSTRAINT tabcol_alt UNIQUE (tab_id,col_id)
        );
GRANT SELECT ON TABLE example.tabcol TO PUBLIC;

DROP TABLE IF EXISTS example.entattval CASCADE;
CREATE TABLE example.entattval
        ( ent_id BIGINT NOT NULL
        , tabcol_id BIGINT NOT NULL REFERENCES example.tabcol(tabcol_id)
        , val_id BIGINT NOT NULL REFERENCES example.zvalue(val_id)
        , PRIMARY KEY (ent_id, tabcol_id, val_id)
        );
GRANT SELECT ON TABLE example.entattval TO PUBLIC;

BTW:这是专为支持系统目录而量身定做的;你可能需要做一些改变。

答案 2 :(得分:1)

这真的是这个dba.SE帖子的重复:

https://dba.stackexchange.com/questions/27057/model-with-variable-number-of-properties-of-different-types

使用hstore,json,xml,EAV模式,...在该帖子上查看我的答案。

答案 3 :(得分:0)

根据查询的数量和数据库的大小,您可以:

  1. 制作广泛的表格
  2. 制作attibutes表和car_attributes表,其中:cars - > car_attributes - >属性
  3. 由于联接较少,

    #1会使查询更快,更容易,但#2更灵活

答案 4 :(得分:0)

由您需要支持的管理员界面:

  • 如果存在管理例如传输类型的接口,则应将其存储在单独的实体中。 (你的选择3)
  • 如果没有这样的接口,最好存储类似可枚举的类型值。当你需要另一个(例如'半自动'用于传输)时,你只会在数据库模式中添加它,事实上这将是最容易支持和最快的执行

答案 5 :(得分:0)

我会创建create table CarAttributes 列AttributeID,CarID,PropertyName,PropertyValue。 当返回reslut set时,我们将其保存在IDictionary中。 它允许您根据需要添加任意数量的行,而无需添加新列。