どちらの問題も、(変更された)JSON要素をネスト解除して集約する必要があります。どちらの問題でも、使いやすくするための関数を作成します。
create function remove_element(p_value jsonb, p_to_remove jsonb)
returns jsonb
as
$$
select jsonb_agg(t.element order by t.idx)
from jsonb_array_elements(p_value) with ordinality as t(element, idx)
where not t.element @> p_to_remove;
$$
language sql
immutable;
この関数は、次のように使用できます。 UPDATEステートメントの場合:
update the_table
set the_column = remove_element(the_column, '{"ModuleId": 1}')
where ...
2番目の問題については、同様の機能が役立ちます。
create function change_value(p_value jsonb, p_what jsonb, p_new jsonb)
returns jsonb
as
$$
select jsonb_agg(
case
when t.element @> p_what then t.element||p_new
else t.element
end order by t.idx)
from jsonb_array_elements(p_value) with ordinality as t(element, idx);
$$
language sql
immutable;
||
演算子は既存のキーを上書きするため、これにより古い名前が新しい名前に効果的に置き換えられます。
次のように使用できます:
update the_table
set the_column = change_value(the_column, '{"ModuleId": 1}', '{"ModuleName": "CBA"}')
where ...;
JSON値を渡すことは、関数の使用を非常に制限するキーをハードコーディングするよりも少し柔軟だと思います。最初の関数を使用して、複数のキーを比較することで配列要素を削除することもできます。
関数を作成したくない場合は、関数呼び出しをselect
に置き換えます。 関数から。