我想修复或验证PostgreSQL(v10.7)中JSON对象的密钥。
例如,我有一个名为service_config的JSON对象,它看起来像;
{"con_type": "Foo", "capacity": 2, "capacity_unit": "gbps"}
我有桌子:
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"}
现在,每当我在表中插入行时,我都想确保或验证service_config列是否包含上面提到的所有键,不多也不少。但是,键的值可能为空。
在Postgres中是否可能和/或有更好的方法来做到这一点?
可能的解决方案:
1-验证后端API上的service_config并确保所有密钥都在那里。 (当前已安装并且正在运行)
2-在Postgres中编写一个函数,以在插入和更新时验证service_config。 (可行但乏味)
Limitation:我无法在Postgres中添加任何扩展名。
我想确保或验证service_config列包含上面提到的所有键,仅此而已。但是,键的值可能为空。
将它们分成几列。
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
这些列将始终存在。它们的值可以为null。您可以添加每列check
约束和索引。无需其他验证。
如果仍然需要json,请使用jsonb_build_object
。
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
,因为在Postgres中char
没有任何优势。请参见char
中的提示>
这三种类型之间没有性能差异,除了使用空白填充类型时增加的存储空间,以及在存储到受长度限制的列中时需要一些额外的CPU周期来检查长度。尽管character(n)在某些其他数据库系统中具有性能优势,但在PostgreSQL中却没有这种优势。实际上,character(n)通常是这三个中最慢的,因为它需要额外的存储成本。 在大多数情况下,应使用文本或字符变化。