I SQLite, json_each()
er en tabelværdi-funktion, der følger den JSON-værdi, der er angivet som dets første argument, og returnerer en tabel bestående af en række for hvert array-element eller objektmedlem.
Vi angiver JSON-værdien som et argument, når vi kalder funktionen.
Vi kan valgfrit sende et andet argument, som specificerer en sti at starte fra. Når vi gør dette, json_each()
behandler denne vej som elementet på øverste niveau.
json_each()
funktion går kun de umiddelbare børn af arrayet eller objektet på øverste niveau, eller blot selve elementet på øverste niveau, hvis elementet på øverste niveau er en primitiv værdi. For rekursivt at gå gennem JSON-understrukturen, brug json_tree()
i stedet.
Syntaks
Vi kan bruge funktionen på følgende måder:
json_each(X)
json_each(X,P)
Hvor X
repræsenterer JSON og P
er et valgfrit argument, der repræsenterer stien, der skal behandles som det øverste niveau.
Eksempel
Her er et eksempel for at demonstrere, hvordan det virker:
SELECT * FROM json_each('{ "name" : "Woof", "age" : 10 }');
Resultat:
+------+-------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+---------+------+----+--------+---------+------+ | name | Woof | text | Woof | 2 | null | $.name | $ | | age | 10 | integer | 10 | 4 | null | $.age | $ | +------+-------+---------+------+----+--------+---------+------+
Vi kan se, at hvert objektmedlem har sin egen række med nogle nyttige oplysninger, såsom dens type (SQL-tekstværdi), sti osv.
Med hensyn til id
kolonne, ifølge SQLite-dokumentationen er dette et internt husholdningsnummer, hvis beregning kan ændre sig i fremtidige udgivelser. Den eneste garanti er, at id
kolonne vil være forskellig for hver række.
Den overordnede kolonne er altid null
når du kalder json_each()
. Denne kolonne bliver mere meningsfuld, når du bruger json_tree()
.
Array
I dette eksempel er JSON-værdien en matrix:
SELECT * FROM json_each('[ 10, 30, 45 ]');
Resultat:
+-----+-------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +-----+-------+---------+------+----+--------+---------+------+ | 0 | 10 | integer | 10 | 1 | null | $[0] | $ | | 1 | 30 | integer | 30 | 2 | null | $[1] | $ | | 2 | 45 | integer | 45 | 3 | null | $[2] | $ | +-----+-------+---------+------+----+--------+---------+------+
Angiv en sti
Vi kan bruge et andet argument til at angive en sti, der skal behandles som det øverste niveau.
Eksempel:
SELECT * FROM json_each('{ "a" : 1, "b" : [ 4, 7, 8 ] }', '$.b');
Resultat:
+-----+-------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +-----+-------+---------+------+----+--------+---------+------+ | 0 | 4 | integer | 4 | 5 | null | $.b[0] | $.b | | 1 | 7 | integer | 7 | 6 | null | $.b[1] | $.b | | 2 | 8 | integer | 8 | 7 | null | $.b[2] | $.b | +-----+-------+---------+------+----+--------+---------+------+
Større dokument
I dette eksempel bruger vi et større JSON-dokument. Lad os først kalde json_each()
uden at angive en sti:
SELECT * FROM json_each('[
{
"user" : "Spike",
"age" : 30,
"scores" : [ 9, 7, 3 ]
},
{
"user" : "Faye",
"age" : 25,
"scores" : [ 90, 87, 93 ]
},
{
"user" : "Jet",
"age" : 40,
"scores" : [ 50, 38, 67 ]
}
]'
);
Resultat:
+-----+----------------------------------------------+--------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +-----+----------------------------------------------+--------+------+----+--------+---------+------+ | 0 | {"user":"Spike","age":30,"scores":[9,7,3]} | object | N/A | 1 | N/A | $[0] | $ | | 1 | {"user":"Faye","age":25,"scores":[90,87,93]} | object | N/A | 11 | N/A | $[1] | $ | | 2 | {"user":"Jet","age":40,"scores":[50,38,67]} | object | N/A | 21 | N/A | $[2] | $ | +-----+----------------------------------------------+--------+------+----+--------+---------+------+
I dette tilfælde er vores JSON-værdi et array, der indeholder tre objekter. Hvert objekt er angivet i resultaterne.
Lad os nu kalde json_each()
igen, men denne gang angiver vi en sti:
SELECT * FROM json_each('[
{
"user" : "Spike",
"age" : 30,
"scores" : [ 9, 7, 3 ]
},
{
"user" : "Faye",
"age" : 25,
"scores" : [ 90, 87, 93 ]
},
{
"user" : "Jet",
"age" : 40,
"scores" : [ 50, 38, 67 ]
}
]',
'$[1]'
);
Resultat:
+--------+------------+---------+------+----+--------+-------------+------+ | key | value | type | atom | id | parent | fullkey | path | +--------+------------+---------+------+----+--------+-------------+------+ | user | Faye | text | Faye | 13 | null | $[1].user | $[1] | | age | 25 | integer | 25 | 15 | null | $[1].age | $[1] | | scores | [90,87,93] | array | null | 17 | null | $[1].scores | $[1] | +--------+------------+---------+------+----+--------+-------------+------+
I dette tilfælde valgte jeg det andet array-element ved at angive [1]
(arrays er nul baseret i SQLite).
Resultatet er, at outputtet indeholder information om det andet array-element.
Denne gang kan vi se, at path
kolonne indeholder $[1]
.
Lad os gå dybere:
SELECT * FROM json_each('[
{
"user" : "Spike",
"age" : 30,
"scores" : [ 9, 7, 3 ]
},
{
"user" : "Faye",
"age" : 25,
"scores" : [ 90, 87, 93 ]
},
{
"user" : "Jet",
"age" : 40,
"scores" : [ 50, 38, 67 ]
}
]',
'$[1].scores'
);
Resultat:
+-----+-------+---------+------+----+--------+----------------+-------------+ | key | value | type | atom | id | parent | fullkey | path | +-----+-------+---------+------+----+--------+----------------+-------------+ | 0 | 90 | integer | 90 | 18 | null | $[1].scores[0] | $[1].scores | | 1 | 87 | integer | 87 | 19 | null | $[1].scores[1] | $[1].scores | | 2 | 93 | integer | 93 | 20 | null | $[1].scores[2] | $[1].scores | +-----+-------+---------+------+----+--------+----------------+-------------+
Nu får vi en række for hvert element i scores
array.
Filtrering af forespørgslen
Vi kan ændre vores forespørgsel for at filtrere resultaterne ud fra et givet kriterium. For eksempel:
SELECT
fullkey,
value
FROM json_each('[
{
"user" : "Spike",
"age" : 30,
"scores" : [ 9, 7, 3 ]
},
{
"user" : "Faye",
"age" : 25,
"scores" : [ 90, 87, 93 ]
},
{
"user" : "Jet",
"age" : 40,
"scores" : [ 50, 38, 67 ]
}
]'
)
WHERE json_each.value LIKE '%Faye%';
Resultat:
+---------+----------------------------------------------+ | fullkey | value | +---------+----------------------------------------------+ | $[1] | {"user":"Faye","age":25,"scores":[90,87,93]} | +---------+----------------------------------------------+
Et databaseeksempel
Antag, at vi har følgende tabel:
SELECT * FROM guests;
Resultat:
+-------+--------------------------------------------------+ | guest | lunch | +-------+--------------------------------------------------+ | Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"] | | Amy | ["Vegetable Quiche", "Apple", "Fruit Juice"] | | Rohit | ["Beef Curry", "Dragonfruit", "Vegetable Juice"] | | Igor | ["Chicken Pie", "Jackfruit", "Fruit Juice"] | | Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | +-------+--------------------------------------------------+
Denne tabel kaldet guests
har to kolonner. Den første kolonne indeholder navnet på gæsten, og den anden kolonne indeholder deres frokostbestilling. De kan bestille tre retter til frokost. Deres frokostbestilling er i form af et array, hvor hver ret er et element i arrayet.
Her er et eksempel på at køre en forespørgsel, der inkorporerer json_each()
mod denne tabel:
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple Juice';
Resultat:
+-------+-------------------------------------------------+ | guest | lunch | +-------+-------------------------------------------------+ | Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"] | | Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | +-------+-------------------------------------------------+
Her returnerede vi alle gæster, der bestilte æblejuice til deres frokost, sammen med deres fulde frokostbestilling.
Hvis vi ønsker at returnere alle gæster, der har bestilt æble “noget”, kan vi gøre dette:
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Resultat:
+-------+-------------------------------------------------+ | guest | lunch | +-------+-------------------------------------------------+ | Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"] | | Amy | ["Vegetable Quiche", "Apple", "Fruit Juice"] | | Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | +-------+-------------------------------------------------+
Bemærk, at jeg brugte DISTINCT
klausul i min forespørgsel. Dette sikrer, at vi ikke får flere rækker retur for den samme gæst. For at demonstrere, hvad jeg mener, her er forespørgslen igen, men uden DISTINCT
klausul:
SELECT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Resultat:
+-------+-------------------------------------------------+ | guest | lunch | +-------+-------------------------------------------------+ | Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"] | | Amy | ["Vegetable Quiche", "Apple", "Fruit Juice"] | | Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | +-------+-------------------------------------------------+
Denne gang dukker Aisha op to gange. Det skyldes, at hun bestilte to æbleretter til frokost – Æbletærte og Æblejuice.