PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie kann ich ein bestimmtes JSON-Objekt aus dem JSON-Array ändern oder entfernen, das im JSONB-Spaltentyp in PostgreSQL mit der Where-Klausel gespeichert ist?

Beide Probleme erfordern das Aufheben der Verschachtelung und das erneute Aggregieren der (modifizierten) JSON-Elemente. Für beide Probleme würde ich eine Funktion erstellen, um die Verwendung zu vereinfachen.

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;

So kann die Funktion z.B. in einer UPDATE-Anweisung:

update the_table
  set the_column = remove_element(the_column, '{"ModuleId": 1}')
where ...

Für das zweite Problem bietet sich eine ähnliche Funktion an.

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;

Der || Der Operator überschreibt einen vorhandenen Schlüssel, sodass der alte Name effektiv durch den neuen Namen ersetzt wird.

Sie können es wie folgt verwenden:

update the_table
  set the_column = change_value(the_column, '{"ModuleId": 1}', '{"ModuleName": "CBA"}')
where ...;

Ich denke, das Übergeben der JSON-Werte ist etwas flexibler als das Festcodieren der Schlüssel, wodurch die Verwendung der Funktion sehr eingeschränkt wird. Die erste Funktion könnte auch verwendet werden, um Array-Elemente zu entfernen, indem mehrere Schlüssel verglichen werden.

Wenn Sie die Funktionen nicht erstellen möchten, ersetzen Sie den Funktionsaufruf durch select aus den Funktionen.