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

UPDATE mit jsonb_set() wirkt sich nur auf ein Objekt im verschachtelten Array aus

Erklärung

Die Unterauswahl im FROM -Klausel Ihres UPDATE gibt drei zurück Reihen. Aber jede Zeile in der Zieltabelle kann nur einmal aktualisiert werden in einem einzigen UPDATE Befehl. Das Ergebnis ist, dass Sie nur den Effekt von einem sehen dieser drei Zeilen.

Oder in den Worten von dem Handbuch :

Übrigens:Nennen Sie Ihre Unterabfrage nicht "cte". Es ist kein allgemeiner Tabellenausdruck .

Richtiges UPDATE

UPDATE table_ t
SET    value_ = jsonb_set(value_, '{iProps}', sub2.new_prop, false)
FROM  (
   SELECT id
        , jsonb_agg(jsonb_set(prop, '{value, rules}', new_rules, false)
                    ORDER BY idx1) AS new_prop
   FROM  (
      SELECT t.id, arr1.prop, arr1.idx1
           , jsonb_agg(jsonb_set(rule, '{ao,sc}', rule #> '{ao,sc,name}', false)
                       ORDER BY idx2) AS new_rules
      FROM table_ t
         , jsonb_array_elements(value_->'iProps')       WITH ORDINALITY arr1(prop,idx1)
         , jsonb_array_elements(prop->'value'->'rules') WITH ORDINALITY arr2(rule,idx2)
      GROUP  BY t.id, arr1.prop, arr1.idx1
      ) sub1
   GROUP  BY id
   ) sub2
WHERE t.id = sub2.id;

db<>fiddle hier

Verwenden Sie jsonb_set() auf jedem Objekt (Array-Element), bevor sie wieder zu einem Array aggregiert werden. Zuerst auf der Blattebene und noch einmal auf der tieferen Ebene.

Ich habe id hinzugefügt als PRIMARY KEY zum Tisch. Wir brauchen eine eindeutige Spalte, um die Zeilen getrennt zu halten.

Der hinzugefügte ORDER BY kann erforderlich sein oder nicht. Hinzugefügt, um die ursprüngliche Bestellung zu garantieren.

Wenn Ihre Daten so regelmäßig sind wie die Stichprobe, könnte ein relationales Design mit dedizierten Spalten natürlich eine einfachere Alternative sein. Siehe