修复 PostgreSQL 中的 JSON 个键

Fix JSON keys in PostgreSQL

我想修复或验证 PostgreSQL(v10.7) 中 JSON 对象的键。

例如,我有一个名为 service_config 的 JSON 对象,它看起来像;

{"con_type": "Foo", "capacity": 2, "capacity_unit": "gbps"}

我有 table:

 id(serial)   service_name(char)   service_type(char)    service_config(JSON)
-----------+---------------------+---------------------+---------------------
    1      |          com        |        ethernet     | {"con_type": "ddc", "capacity": 2, "capacity_unit": "gbps"}
    2      |          res        |        gpon         | {"con_type": "ftth", "capacity": 1, "capacity_unit": "gbps"} 

现在,每当我向 table 中插入行时,我都想确保或验证 service_config 列包含所有的键上面说了,不多也不少。但是,键可能有空值。

这在 Postgres 中可行吗and/or有没有更好的方法来做到这一点?

可能的解决方案

1- 在后端验证 service_config API 并确保所有密钥都在那里。 (目前正在工作)

2- 在 Postgres 中编写一个函数以在插入和更新时验证 service_config。 (可行但乏味)

限制:我无法在 Postgres 中添加任何扩展。

I want to make sure or validate that the service_config column contains all the keys that are mentioned above, no more, no less. However, there could be null value for the keys.

将它们变成列。

JSON 当您需要将一些数据转储到一行中并且您不确定它会是什么时,它非常有用。现在您已经确定它会是什么,并且您想要更多的约束,这就是专栏最擅长的。

alter table whatever add column con_type text;
alter table whatever add column capacity integer;
alter table whatever add column capacity_unit text;

update whatever set
  con_type = data->'con_type',
  capacity = data->'capacity',
  capacity_unit = data->'capacity_unit';

alter table whatever drop column data

列将永远存在。它们的值可能为空。您可以添加每列 check 约束和索引。无需额外验证。

如果您还需要json,请使用jsonb_build_object

select
  jsonb_build_object(
    'con_type', con_type,
    'capacity', capacity,
    'capacity_unit', capacity_unit
  )
from whatever;

而且,如果您出于兼容性目的需要它,您可以将其设为视图。

create view whatever_as_json
select
  *,
  jsonb_build_object(
    'con_type', con_type,
    'capacity', capacity,
    'capacity_unit', capacity_unit
  ) as data
from whatever;

请注意,我使用 text,而不是 char,因为 char 在 Postgres 中没有优势。请参阅 8.3. Character Types

中的提示

There is no performance difference among these three types, apart from increased storage space when using the blank-padded type, and a few extra CPU cycles to check the length when storing into a length-constrained column. While character(n) has performance advantages in some other database systems, there is no such advantage in PostgreSQL; in fact character(n) is usually the slowest of the three because of its additional storage costs. In most situations text or character varying should be used instead.