In SQLite, json_each()
is een functie met tabelwaarde die de JSON-waarde laat lopen die als eerste argument is opgegeven en een tabel retourneert die uit één rij bestaat voor elk arrayelement of objectlid.
We geven de JSON-waarde als argument wanneer we de functie aanroepen.
We kunnen optioneel een tweede argument doorgeven, dat een pad specificeert om vanaf te beginnen. Wanneer we dit doen, json_each()
behandelt dat pad als het element op het hoogste niveau.
De json_each()
functie leidt alleen de directe kinderen van de array of het object op het hoogste niveau, of alleen het element op het hoogste niveau zelf als het element op het hoogste niveau een primitieve waarde is. Om recursief door de JSON-substructuur te lopen, gebruikt u json_tree()
in plaats daarvan.
Syntaxis
We kunnen de functie op de volgende manieren gebruiken:
json_each(X)
json_each(X,P)
Waar X
vertegenwoordigt de JSON, en P
is een optioneel argument dat het pad vertegenwoordigt dat als het hoogste niveau moet worden behandeld.
Voorbeeld
Hier is een voorbeeld om te demonstreren hoe het werkt:
SELECT * FROM json_each('{ "name" : "Woof", "age" : 10 }');
Resultaat:
+------+-------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+---------+------+----+--------+---------+------+ | name | Woof | text | Woof | 2 | null | $.name | $ | | age | 10 | integer | 10 | 4 | null | $.age | $ | +------+-------+---------+------+----+--------+---------+------+
We kunnen zien dat elk objectlid zijn eigen rij heeft met wat nuttige informatie, zoals het type (SQL-tekstwaarde), pad, enz.
Met betrekking tot de id
kolom, volgens de SQLite-documentatie is dit een intern huishoudnummer, waarvan de berekening in toekomstige releases kan veranderen. De enige garantie is dat de id
kolom zal voor elke rij anders zijn.
De bovenliggende kolom is altijd null
bij het aanroepen van json_each()
. Deze kolom wordt zinvoller bij gebruik van json_tree()
.
Array
In dit voorbeeld is de JSON-waarde een array:
SELECT * FROM json_each('[ 10, 30, 45 ]');
Resultaat:
+-----+-------+---------+------+----+--------+---------+------+ | 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] | $ | +-----+-------+---------+------+----+--------+---------+------+
Geef een pad op
We kunnen een tweede argument gebruiken om een pad op te geven dat als het hoogste niveau moet worden behandeld.
Voorbeeld:
SELECT * FROM json_each('{ "a" : 1, "b" : [ 4, 7, 8 ] }', '$.b');
Resultaat:
+-----+-------+---------+------+----+--------+---------+------+ | 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 | +-----+-------+---------+------+----+--------+---------+------+
Groter document
In dit voorbeeld gebruiken we een groter JSON-document. Laten we eerst json_each()
. aanroepen zonder een pad op te geven:
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 ]
}
]'
);
Resultaat:
+-----+----------------------------------------------+--------+------+----+--------+---------+------+ | 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] | $ | +-----+----------------------------------------------+--------+------+----+--------+---------+------+
In dit geval is onze JSON-waarde een array die drie objecten bevat. Elk object wordt vermeld in de resultaten.
Laten we nu json_each()
. aanroepen nogmaals, maar deze keer zullen we een pad specificeren:
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]'
);
Resultaat:
+--------+------------+---------+------+----+--------+-------------+------+ | 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] | +--------+------------+---------+------+----+--------+-------------+------+
In dit geval heb ik het tweede array-element gekozen door [1]
op te geven (arrays zijn gebaseerd op nul in SQLite).
Het resultaat is dat de uitvoer informatie bevat over het tweede array-element.
Deze keer kunnen we zien dat het path
kolom bevat $[1]
.
Laten we dieper gaan:
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'
);
Resultaat:
+-----+-------+---------+------+----+--------+----------------+-------------+ | 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 krijgen we een rij voor elk element in de scores
array.
De zoekopdracht filteren
We kunnen onze zoekopdracht aanpassen om de resultaten te filteren op basis van een bepaald criterium. Bijvoorbeeld:
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%';
Resultaat:
+---------+----------------------------------------------+ | fullkey | value | +---------+----------------------------------------------+ | $[1] | {"user":"Faye","age":25,"scores":[90,87,93]} | +---------+----------------------------------------------+
Een databasevoorbeeld
Stel dat we de volgende tabel hebben:
SELECT * FROM guests;
Resultaat:
+-------+--------------------------------------------------+ | 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"] | +-------+--------------------------------------------------+
Deze tabel heet guests
heeft twee kolommen. De eerste kolom bevat de naam van de gast en de tweede kolom bevat hun lunchbestelling. Ze kunnen drie gerechten bestellen voor de lunch. Hun lunchbestelling heeft de vorm van een array, waarbij elk gerecht een element in de array is.
Hier is een voorbeeld van het uitvoeren van een query die json_each()
. bevat tegen deze tafel:
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple Juice';
Resultaat:
+-------+-------------------------------------------------+ | guest | lunch | +-------+-------------------------------------------------+ | Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"] | | Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | +-------+-------------------------------------------------+
Hier hebben we alle gasten teruggestuurd die appelsap bestelden bij hun lunch, samen met hun volledige lunchbestelling.
Als we alle gasten die appel "iets" bestelden willen teruggeven, kunnen we dit doen:
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Resultaat:
+-------+-------------------------------------------------+ | 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"] | +-------+-------------------------------------------------+
Merk op dat ik de DISTINCT
. heb gebruikt clausule in mijn vraag. Dit zorgt ervoor dat we niet meerdere rijen terugkrijgen voor dezelfde gast. Om te demonstreren wat ik bedoel, hier is de vraag opnieuw, maar zonder de DISTINCT
clausule:
SELECT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Resultaat:
+-------+-------------------------------------------------+ | 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"] | +-------+-------------------------------------------------+
Deze keer verschijnt Aisha twee keer. Dat komt omdat ze twee appelgerechten bestelde voor de lunch:appeltaart en appelsap.