Предполагая, что у вас есть уникальное ограничение на notificationid
(например, поскольку это первичный ключ, нет необходимости в сохраненной функции или цикле:
with data (j) as (
values ('
{
"list": [{
"notificationId": 123,
"userId": 444
},
{
"notificationId": 456,
"userId": 789
}
]
}'::jsonb)
)
insert into notification (notificationid, userid)
select (e.r ->> 'notificationId')::int, (e.r ->> 'userId')::int
from data d, jsonb_array_elements(d.j -> 'list') as e(r)
on conflict (notificationid) do update
set userid = excluded.userid;
Первым шагом в этом операторе является поворотмассив в список строк, это то, что:
select e.*
from data d, jsonb_array_elements(d.j -> 'list') as e(r)
делает. Учитывая ваш пример JSON, это возвращает две строки со значением JSON в каждой:
r
--------------------------------------
{"userId": 444, "notificationId": 123}
{"userId": 789, "notificationId": 456}
Это тогдаразделить на два целочисленных столбца:
select (e.r ->> 'notificationId')::int, (e.r ->> 'userId')::int
from data d, jsonb_array_elements(d.j -> 'list') as e(r)
Итак, мы получим:
int4 | int4
-----+-----
123 | 444
456 | 789
И этот результат используется в качестве входных данных для оператора INSERT
.
Затем предложение on conflict
выполняет вставку или обновление в зависимости от наличия строки, идентифицируемой столбцом notificationid
, который должен иметь уникальный индекс.