CodeGym /Corsi /SQL SELF /Unione e modifica di oggetti JSON con l'operatore || e la...

Unione e modifica di oggetti JSON con l'operatore || e la funzione jsonb_concat()

SQL SELF
Livello 34 , Lezione 0
Disponibile

Se JSONB è come un baule magico dove buttiamo i dati, allora || e jsonb_concat() sono gli attrezzi che ci permettono di unire questi bauli o cambiare quello che c'è dentro. Nella vita reale, ti può capitare di dover unire più oggetti JSON, aggiungere dati da uno all'altro o fondere array in una sola lista.

Per esempio, immagina di avere due oggetti JSONB:

{"nome": "Alice", "età": 25}

e

{"città": "Wonderland", "hobby": ["lettura", "scacchi"]}

Vuoi ottenere:

{"nome": "Alice", "età": 25, "città": "Wonderland", "hobby": ["lettura", "scacchi"]}

Oppure unire due array JSONB:

[1, 2, 3]

e

[4, 5, 6]

così che il risultato sia:

[1, 2, 3, 4, 5, 6]

Tutto questo si fa con || o jsonb_concat(). Vediamo come funziona.

L'operatore || per unire JSONB

L'operatore || ti permette di unire due oggetti o array JSONB in PostgreSQL. È semplice, veloce e facilissimo da usare. Ecco le regole base:

  • Se unisci due oggetti JSONB, l'oggetto risultante avrà tutte le chiavi e i valori di entrambi.
  • Se le chiavi si sovrappongono, il valore dell'operando di destra sostituisce quello di sinistra.
  • Se unisci array JSONB, gli elementi dell'array di sinistra e di destra vengono messi insieme in un unico array.

Esempio 1: Unione di due oggetti JSONB

SELECT '{"nome": "Alice", "età": 25}'::jsonb || '{"città": "Wonderland", "hobby": ["lettura", "scacchi"]}'::jsonb AS oggetto_unito;

Risultato:

{"nome": "Alice", "età": 25, "città": "Wonderland", "hobby": ["lettura", "scacchi"]}

Esempio 2: Aggiornamento dei valori quando le chiavi coincidono

SELECT '{"nome": "Alice", "età": 25}'::jsonb || '{"età": 30, "città": "Wonderland"}'::jsonb AS oggetto_aggiornato;

Risultato:

{"nome": "Alice", "età": 30, "città": "Wonderland"}

Nota che il valore della chiave "età" dell'oggetto di destra ha sostituito quello di sinistra.

Esempio 3: Unione di array

SELECT '[1, 2, 3]'::jsonb || '[4, 5, 6]'::jsonb AS array_unito;

Risultato:

[1, 2, 3, 4, 5, 6]

La funzione jsonb_concat() per unire JSONB

La funzione jsonb_concat() funziona come l'operatore ||, ma è più flessibile se ti serve usarla in funzioni, trigger o query dinamiche. Prende due argomenti di tipo JSONB e restituisce il risultato unito.

Esempio: uso di jsonb_concat()

SELECT jsonb_concat('{"a": 1, "b": 2}'::jsonb, '{"b": 3, "c": 4}'::jsonb) AS combinato;

Risultato:

{"a": 1, "b": 3, "c": 4}

Unione di oggetti e array: particolarità e dettagli

Quando unisci oggetti con chiavi che coincidono, ricorda che i valori dell'oggetto di destra hanno la precedenza.

Per esempio:

SELECT '{"chiave1": "valore1"}'::jsonb || '{"chiave1": "valore2"}'::jsonb AS risultato;

Risultato:

{"chiave1": "valore2"}

Se vuoi evitare la sovrascrittura dei valori, meglio mettere questi dati in chiavi diverse o usare un altro approccio (tipo un array).

Invece gli array vengono sempre uniti aggiungendo gli elementi dell'array di destra a quello di sinistra. Per esempio:

SELECT '["a", "b"]'::jsonb || '["c", "d"]'::jsonb AS risultato;

Risultato:

["a", "b", "c", "d"]

Se dentro l'array ci sono oggetti, l'ordine viene mantenuto:

SELECT '[{"id": 1}, {"id": 2}]'::jsonb || '[{"id": 3}]'::jsonb AS risultato;

Risultato:

[{"id": 1}, {"id": 2}, {"id": 3}]

Esempi pratici

Aggiornamento del profilo utente. Supponiamo di avere una tabella utenti dove i profili sono salvati in formato JSONB:

CREATE TABLE utenti (
    id SERIAL PRIMARY KEY,
    profilo JSONB
);

INSERT INTO utenti (profilo) VALUES ('{"nome": "Alice", "età": 25}');

Ora vogliamo aggiungere la città di residenza:

UPDATE utenti 
SET profilo = profilo || '{"città": "Wonderland"}'
WHERE id = 1;

Risultato della query:

{"nome": "Alice", "età": 25, "città": "Wonderland"}

Unione dei dati sugli ordini. Mettiamo di avere una tabella ordini:

CREATE TABLE ordini (
    id SERIAL PRIMARY KEY,
    dettagli JSONB
);

INSERT INTO ordini (dettagli) VALUES ('{"articoli": [{"prodotto": "laptop", "quantità": 1}]}');

Ora aggiungiamo un altro prodotto all'ordine:

UPDATE ordini
SET dettagli = jsonb_set(
    dettagli,
    '{articoli}',
    dettagli->'articoli' || '[{"prodotto": "mouse", "quantità": 2}]'::jsonb
)
WHERE id = 1;

Risultato della query:

{"articoli": [{"prodotto": "laptop", "quantità": 1}, {"prodotto": "mouse", "quantità": 2}]}

Differenze tra || e jsonb_concat()

Dal punto di vista funzionale, l'operatore || e la funzione jsonb_concat() sono identici. Usa || se scrivi query semplici, perché è più corto. La funzione jsonb_concat() è comoda quando ti serve chiamarla esplicitamente dentro un programma o un trigger.

Errori tipici e come evitarli

Errore: tentativo di unire tipi incompatibili.

SELECT '{"chiave": "valore"}'::jsonb || '["valore"]'::jsonb;

Risultato:

ERROR:  cannot concatenate jsonb objects and arrays

Qui a sinistra c'è un oggetto, a destra un array — PostgreSQL non può unirli così. Per far funzionare l'operazione, entrambi gli operandi devono essere dello stesso tipo: o due oggetti, o due array.

Dimenticanza: mancanza di indici quando lavori con JSONB

Se filtri spesso i dati sui valori dentro i campi JSONB e non hai indici — le query possono diventare lentissime. Non è un errore classico, ma le conseguenze sulle performance si sentono. Ricordati di usare gli indici GIN:

CREATE INDEX idx_dati_profilo ON dipendenti USING gin(profilo);
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION