我正在开始一个新项目,但是在为数据库找到正确的设计时遇到了一些麻烦。
数据库域具有许多彼此相似但具有几个不同字段的实体。随着时间的流逝,此字段可能会更改,其中许多都是枚举。目的是设计一种数据库,以便可以通过管理控制台来控制字段及其可能的值。
我的想法是拥有一个实体Super entity
,该实体存储所有实体之间的所有公共字段,并拥有一个EntityCharacteristics
,该实体将带有外键的实体特征存储到Characteristic
表中将存储有关特征的信息,从而可以使用此信息来创建表单字段,例如
CharacteristicName: Age
Placeholder: Enter your age...
InputType: text
CharacteristicType: Integer
例如,可能需要为selectbox的InputType存储可能的值,该值可能是枚举类型。
此外,SuperEntity
将具有一个Entity_type字段,该字段将连接到一个EntityType
表,并且该表将连接到一个PossibleEntityCharacteristics
,该字段将可能的特征存储到某个实体类型。 / p>
我的问题是如何将值存储在EntityCharacteristics
中,因为它们可以是不同的类型,布尔值,文本,整数,枚举等。以及如何将可能的值存储在枚举类型中,杰森还是使用另一个表中某个特性的可能值?我如何确定插入EntityCharacteristics
中的值是正确的类型,并且包含可能的枚举值?
也许这根本不是一个好的设计,我不应该这样想,而只是将数据存储在具有许多字段的纯表中。但是我想提供一种解决方案,它可以随时轻松地为不同的相似实体更改现有字段和字段值,并且必须更改表架构似乎并不是一个好主意。我计划用支持Json的PostgreSQL实现此功能,而PostgreSQL可能适合这里,但是由于我从未在Sql中使用此数据类型,所以我不知道这是一个好主意。
我想知道您对此的看法,在此先感谢您。
请注意:我正在考虑的数据库模型类似于https://stackoverflow.com/a/7423459,但有点复杂,并且没有嵌套。
答案 0 :(得分:2)
这有点基于意见,但是无论如何:
我会去一个单一的表,其中包含所有类型的对象共有的所有属性的列。然后有一个额外的JSONB
列,用于存储在不同类型之间可能有所不同的各个属性。
您可以更进一步,在第二个表中创建“类型描述”,该表定义了类型的允许属性。然后可以通过管理UI,也可以使用它来验证放入基表的“动态”属性中的数据。
类似这样的东西:
create table object_type
(
id integer primary key,
name text not null,
allowed_attributes jsonb not null
);
create table objects
(
id integer primary key,
name text not null,
object_type_id integer not null references object_type,
attributes jsonb
);
insert into object_type (id, name, allowed_attributes)
values
(1, 'spaceship', '{"seats": "integer", "color": "text"}'::jsonb),
(2, 'book', '{"number_of_pages": "integer", "color": "text"}'::jsonb);
insert into objects (id, name, object_type_id, attributes)
values
(1, 'Heart Of Gold', 1, '{"seats": 4, "color": "white"}'),
(2, 'H2G2', 2, '{"number_of_pages": 42, "color": "black", "published_in": 1979}');
现在,在以上示例中,published_in
是基于object_type
中相应行的不允许的属性。这些行可以用例如以下查询:
select *
from (
select *,
attributes - (select array_agg(t.k)
from object_type ot, jsonb_object_keys(ot.allowed_attributes) as t(k)
where ot.id = o.object_type_id) as invalid_attributes
from objects o
) t
where invalid_attributes <> '{}';
您甚至可以构建一个触发器,在插入或更新对象时执行这种检查。
使用json_typeof()
函数,您还可以验证提供的键值是否与object_type
中定义的数据类型相匹配