Operatorii -> și ->> în SQLite

Funcții JSON SQLite 3.38.0

Prescurtări pentru citirea din JSON: -> întoarce o bucată de JSON, ->> întoarce valoarea SQL, fără ghilimele.

Sintaxă
json -> cale      -- întoarce JSON (text JSON)
json ->> cale     -- întoarce valoare SQL (TEXT, INTEGER, REAL, NULL)
-- cale: '$.a.b', 'a' (prescurtare pentru '$.a') sau un număr (indice de tablou)

Ce face Operatorii -> și ->>

Operatorii -> și ->> au apărut în SQLite 3.38.0, cu aceeași formă ca în MySQL și PostgreSQL. În stânga stă textul JSON, în dreapta calea. Calea poate fi completă ('$.livrare.cost'), doar un nume de cheie ('oras' înseamnă '$.oras') sau un număr întreg, care alege elementul unui tablou (2 înseamnă '$[2]').

Diferența dintre ei: -> întoarce întotdeauna text JSON, deci un text apare între ghilimele ("Iași") și poate fi dat mai departe altui operator. ->> întoarce o valoare SQL simplă: textul fără ghilimele, numerele ca numere. Pentru valori simple, ->> dă același rezultat ca json_extract.

Operatorii se pot înlănțui: detalii -> 'livrare' ->> 'curier'. Spre deosebire de PostgreSQL, unde ->> întoarce mereu text, în SQLite ->> poate întoarce și INTEGER sau REAL, deci comparațiile numerice merg direct.

Parametri

Parametru Descriere
-> Întoarce reprezentarea JSON a valorii găsite (sau NULL dacă nu există).
->> Întoarce valoarea SQL: TEXT, INTEGER, REAL sau NULL.

Exemple

Exemplele de pe această pagină pornesc de la datele de mai jos. Rulează mai întâi acest cod, apoi exemplul.

CREATE TABLE comenzi (
  id      INTEGER PRIMARY KEY,
  client  TEXT NOT NULL,
  detalii TEXT NOT NULL      -- document JSON
);
INSERT INTO comenzi (client, detalii) VALUES
  ('Ana',   '{"oras": "Iași", "produse": [{"nume": "carte", "pret": 45}, {"nume": "pix", "pret": 5}], "livrare": {"curier": "FAN", "cost": 15}}'),
  ('Vlad',  '{"oras": "Cluj", "produse": [{"nume": "caiet", "pret": 12}], "livrare": {"curier": "Poșta", "cost": 8}}'),
  ('Elena', '{"oras": "Iași", "produse": [], "livrare": {"curier": "FAN", "cost": 15}}');

Exemplul 1: Același câmp citit cu -> și cu ->>

-> păstrează ghilimelele, pentru că rezultatul este JSON. typeof arată că ->> a întors un număr întreg pentru cost.

SELECT detalii -> 'oras'               AS cu_sageata,
       detalii ->> 'oras'              AS cu_doua_sageti,
       detalii -> '$.livrare'          AS livrare_json,
       typeof(detalii ->> '$.livrare.cost') AS tip_cost
FROM comenzi WHERE client = 'Ana';

Rezultat

╭────────────┬────────────────┬────────────────────────────┬──────────╮
│ cu_sageata │ cu_doua_sageti │        livrare_json        │ tip_cost │
╞════════════╪════════════════╪════════════════════════════╪══════════╡
│ "Iași"     │ Iași           │ {"curier":"FAN","cost":15} │ integer  │
╰────────────┴────────────────┴────────────────────────────┴──────────╯

Exemplul 2: Înlănțuire și indice de tablou

detalii -> 'produse' dă tabloul de produse; -> 0 alege primul produs, iar ->> 'nume' îi citește numele.

SELECT client,
       detalii -> 'livrare' ->> 'curier'       AS curier,
       detalii -> 'produse' -> 0 ->> 'nume'    AS primul_produs,
       detalii -> 'produse' -> 0 ->> 'pret'    AS pret
FROM comenzi
ORDER BY id;

Rezultat

╭────────┬────────┬───────────────┬──────╮
│ client │ curier │ primul_produs │ pret │
╞════════╪════════╪═══════════════╪══════╡
│ Ana    │ FAN    │ carte         │   45 │
│ Vlad   │ Poșta  │ caiet         │   12 │
│ Elena  │ FAN    │               │      │
╰────────┴────────┴───────────────┴──────╯

Exemplul 3: ->> în WHERE și ORDER BY

Comenzile din Iași, sortate după costul livrării și apoi după client. Prețul primului produs al Elenei lipsește, deci ->> dă NULL.

SELECT client, detalii ->> '$.livrare.cost' AS cost
FROM comenzi
WHERE detalii ->> 'oras' = 'Iași'
ORDER BY cost, client;

Rezultat

╭────────┬──────╮
│ client │ cost │
╞════════╪══════╡
│ Ana    │   15 │
│ Elena  │   15 │
╰────────┴──────╯

Greșeli frecvente

  • Compari rezultatul lui -> cu un text: detalii -> 'oras' = 'Iași' este fals, pentru că -> întoarce "Iași" cu ghilimele. Pentru comparații folosește ->>.
  • Scrii o cheie cu caractere speciale (spațiu, punct) în forma scurtă. Folosește calea completă cu ghilimele: detalii ->> '$."cod postal"'.
  • Rulezi pe o versiune mai veche de 3.38.0. Operatorii nu există acolo și primești eroare de sintaxă; folosește json_extract.

Comenzi înrudite

  • json_extract: Citește o valoare dintr-un text JSON după o cale de forma $.livrare.cost sau $.produse[0].nume.
  • json_each / json_tree: Transformă un tablou sau un obiect JSON în rânduri, ca să poți filtra, număra și lega elementele lui cu alte tabele.
  • Index pe expresii: Indexează rezultatul unei expresii, de exemplu lower(email) sau un câmp JSON, ca să cauți rapid după valoarea calculată.
  • Coloane generate (GENERATED ALWAYS AS): O coloană a cărei valoare este calculată automat dintr-o expresie peste celelalte coloane ale rândului, la citire sau la scriere.