具有变体数据类型的SQL数据库设计

时间:2018-08-31 11:28:20

标签: sql postgresql database-design

我正在开始一个新项目,但是在为数据库找到正确的设计时遇到了一些麻烦。

数据库域具有许多彼此相似但具有几个不同字段的实体。随着时间的流逝,此字段可能会更改,其中许多都是枚举。目的是设计一种数据库,以便可以通过管理控制台来控制字段及其可能的值。

我的想法是拥有一个实体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,但有点复杂,并且没有嵌套。

1 个答案:

答案 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中定义的数据类型相匹配