[英]In PostgreSQL 9.6, what's the simplest way to expand a JSONB column filled with simple JSON dicts?
Say, I have a table json_table
with a JSONB column, json_field
. 说,我有一个带有JSONB列的表
json_table
, json_field
。 Each element in this column is a single uncomplicated dict, eg, 此列中的每个元素都是单个简单的dict,例如,
{'first_field': 2 , 'second_field': 42}
Is there a way to create a new table were the dicts are turned into columns? 有没有办法创建一个新的表,如果将dicts变成列?
My current approach is as follows: 我目前的做法如下:
CREATE TABLE normal_table ... first_field, second_field ... etc;
INSERT INTO normal_table (
id,
first_field,
second_field,
...
)
SELECT
id,
json_field->>'first_field',
json_field->>'second_field',
...
FROM json_table;
Is there a way to do something like the following? 有没有办法做以下的事情?
SELECT
id,
expand_json_dict(json_field)
FROM json_table;
Or a similar succinct way of doing it? 或者类似的简洁方式呢? The JSONB column has a lot of fields I want to expand, and the queries become unwieldy.
JSONB列有很多我想要扩展的字段,查询变得难以处理。 I've actually made a Python function which generates create/insert scripts.
我实际上已经创建了一个生成创建/插入脚本的Python函数。 Still, I'd love for there to be a nice PostgreSQL way to do it.
尽管如此,我仍然希望有一个很好的PostgreSQL方法来做到这一点。
Any thoughts? 有什么想法吗?
Edit 编辑
The following is the working solution based on feedback here. 以下是基于反馈的工作解决方案。 Thanks guys.
多谢你们。
drop table if exists json_table;
create table json_table (
id int,
json_field jsonb
);
insert into json_table VALUES
(2, ('{"second_field": 43, "first_field": 3}'::jsonb)),
(1, ('{"first_field": 2 , "second_field": 42}'::jsonb));
drop table if exists normal_table;
create table normal_table (
id int,
first_field int,
second_field int
);
insert into normal_table
select (
jsonb_populate_record(
null::normal_table,
jsonb_set(json_field, '{id}', id::text::jsonb)
)
).*
from json_table;
select * from normal_table;
Use the normal_table
type as the base type to the jsonb_populate_record
function: 使用
normal_table
类型作为jsonb_populate_record
函数的基类型:
create table normal_table (
id int,
first_field int,
second_field int
);
with json_table (json_field) as ( values
('{"first_field": 2 , "second_field": 42}'::jsonb)
)
select (jsonb_populate_record(null::normal_table, json_field)).*
from json_table
;
id | first_field | second_field
----+-------------+--------------
| 2 | 42
If it is necessary to generate the id
to be inserted use jsonb_set
: 如果有必要生成要插入的
id
,请使用jsonb_set
:
with json_table (json_field) as ( values
('{"first_field": 2 , "second_field": 42}'::jsonb),
('{"first_field": 5 , "second_field": 1}')
)
select (
jsonb_populate_record(
null::normal_table,
jsonb_set(json_field, '{id}', (row_number() over())::text::jsonb)
)
).*
from json_table
;
id | first_field | second_field
----+-------------+--------------
1 | 2 | 42
2 | 5 | 1
You can create a type (record) that reflects your keys and then use json_populate_record
: 您可以创建反映键的类型(记录),然后使用
json_populate_record
:
create type my_type as (first_field varchar, second_field varchar);
SELECT id, (json_populate_record(null::my_type, json_field)).*
FROM json_table;
If there are keys in the JSON document that are not present in the type, they are simply ignored. 如果JSON文档中的键不存在于类型中,则会忽略它们。 If there are fields in the type definition that don't have a match in the JSON document they will be
null
. 如果类型定义中的字段在JSON文档中没有匹配项,则它们将为
null
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.