具有变体数据类型的 SQL 数据库设计 [关闭]

Posted

技术标签:

【中文标题】具有变体数据类型的 SQL 数据库设计 [关闭]【英文标题】:SQL Database design with variant data types [closed] 【发布时间】:2018-08-31 11:28:19 【问题描述】:

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

数据库域具有许多彼此相似但具有多个不同字段的实体。这个字段可以随着时间的推移而改变,其中许多是枚举。目标是设计数据库,使其可以通过管理仪表板控制字段及其可能的值。

我的想法是有一个实体Super entity 存储所有实体之间的所有公共字段,有一个EntityCharacteristics 将具有外键的实体特征存储到Characteristic 表中,该表将存储有关特征的信息这样就可以使用这些信息创建一个表单字段,想象一下

CharacteristicName: Age
Placeholder: Enter your age...
InputType: text
CharacteristicType: Integer

需要可以为选择框的 InputType 存储可能的值,例如,它是一个类似枚举的类型。 此外,SuperEntity 将有一个 entity_type 字段,该字段将连接到 EntityType 表,并且此表将连接到 PossibleEntityCharacteristics,它将可能的特征存储到某个实体类型。

我的问题是我应该如何将值存储在EntityCharacteristics 中,因为它们可以是不同的类型、布尔值、文本、整数、枚举等。以及如何使用 Json 将可能的值存储在枚举类型中?或者与某个特征的另一个可能值表一起使用?我如何确定插入到 EntityCharacteristics 中的值是正确的类型并且包含枚举的可能值?

也许这根本不是一个糟糕的设计,我不应该这样想,而是将数据存储在具有许多字段的普通表中。但是我想提供一个解决方案,可以随时轻松更改不同相似实体的现有字段和字段值,并且必须更改表模式似乎不是一个好主意。我计划用支持 Json 的 PostgreSQL 来实现这个,它可能适合这里的某个地方,但是由于我从未在 Sql 中使用过这种数据类型,所以我不知道这是否是个好主意。

我想知道您对此的看法,在此先感谢您。

注意:我正在考虑的数据库模型类似于 https://***.com/a/7423459,但稍微复杂一些,并且没有嵌套。

【问题讨论】:

嗨。这是一个常见问题解答。您正在处理 sql/数据库子类型化/继承;了解如何做到这一点。而且您建议通过 EAV 对其进行建模;了解一下。 (您还没有表现出需要如此通用和 DIY,而不仅仅是使用 DDL 委托给 DBMS。) 【参考方案1】:

这有点基于意见,但无论如何:

我会选择一个表,其中包含所有属性的列,这些属性在所有类型的对象中都是通用的。然后有一个额外的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 中定义的数据类型匹配

【讨论】:

感谢您的回复!这似乎是一个不错的实现。我之前想过这样的事情,但是要对字段值实现过滤器,查询 jsons 会有效吗? @FrankWright:是的,JSONB 可以在 Postgres 中高效地被索引 好吧,这似乎是一个很好的解决方案!感谢您的帮助!

以上是关于具有变体数据类型的 SQL 数据库设计 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

应该使用啥类型的数据库来存储数百万家餐馆并查询它们[关闭]

SQL:当1个字段具有多个类别时如何设计数据库?

库存数据库设计[关闭]

Sybase,数据类型

具有变体返回类型的 Delphi Excel UDF

Microsoft SQL Server 查询连接数和关闭连接数