sql >> Databáze >  >> RDS >> PostgreSQL

UPDATE pomocí jsonb_set() ovlivňuje pouze jeden objekt ve vnořeném poli

Vysvětlení

Podvýběr v FROM klauzule vašeho UPDATE vrátí tři řádky. Ale každý řádek v cílové tabulce lze aktualizovat pouze jednou v jediném UPDATE příkaz. Výsledkem je, že uvidíte pouze efekt jednoho z těchto tří řádků.

Nebo slovy příručky :

Stranou:neříkejte svému poddotazu „cte“. Nejedná se o běžný tabulkový výraz .

Správné 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 zde

Použijte jsonb_set() na každý objekt (prvek pole) před jejich agregací zpět do pole. Nejprve na úrovni listů a znovu na hlubší úrovni.

Přidal jsem id jako PRIMARY KEY ke stolu. Potřebujeme nějaký jedinečný sloupec, abychom udrželi řádky oddělené.

Přidáno ORDER BY může a nemusí být vyžadováno. Přidáno, aby byla zaručena původní objednávka.

Samozřejmě, pokud jsou vaše data stejně pravidelná jako ukázka, může být jednodušší alternativou relační návrh s vyhrazenými sloupci. Viz




  1. Identifikace vztahu – mnoho k mnoha

  2. Proč subprocess.Popen nečeká na ukončení podřízeného procesu?

  3. Jak získat počet konkrétních řádků z jiné tabulky v poddotazu

  4. Procházejte sloupce RECORD