postgresql 触发器将 json 数据插入列并保留剩余字段

postgresql triggers to insert json data into columns and keep left over fields

我找到了这个问题
我有类似的情况,但用于插入。 考虑到我在 ndjson 文件中没有 table 但原始 json...

{"x": 1}
{"x": 2, "y": 3}
{"x": 8, "z": 3}
{"x": 5, "y": 2, "z": 3}

我想将数据插入到表单的table中(其中json没有列的字段存储在json列中)

x y json
1 NULL NULL
2 3 NULL
8 NULL {"z": 3}
5 2 {"z": 3}

如何定义我的 table 以便 postgresql 在插入或 \copy

时自动执行

使用运算符 -> 并将值转换为现有常规列值的正确类型。使用删除运算符获取剩余的 JSON 个值。

我在示例中使用了 CTE。相反,使用单个 JSONB 列创建 table json_data 并使用 \copy

将 JSON 文件复制到它
with json_data(json) as (
values
    ('{"x": 1}'::jsonb),
    ('{"x": 2, "y": 3}'),
    ('{"x": 8, "z": 3}'),
    ('{"x": 5, "y": 2, "z": 3}')
)

select 
    (json->'x')::int as x, 
    (json->'y')::int as y, 
    nullif(json- 'x'- 'y', '{}') as json
from json_data

阅读文档中的 JSON Functions and Operators

注意。在 Postgres 10 或更早版本中使用 ->> 运算符而不是 ->.


要在导入 json 数据时自动转换,请定义触发器:

create table json_data(json jsonb);

create or replace function json_data_trigger()
returns trigger language plpgsql as $$
begin
    insert into target_table
    select
        (new.json->>'x')::int, 
        (new.json->>'y')::int, 
        nullif(new.json- 'x'- 'y', '{}');
    return new;
end $$;

create trigger json_data_trigger
before insert on json_data
for each row execute procedure json_data_trigger();

Db<>Fiddle.

中测试