I SQLite, json_each()
är en tabellvärderad funktion som följer JSON-värdet som det första argumentet och returnerar en tabell som består av en rad för varje arrayelement eller objektmedlem.
Vi tillhandahåller JSON-värdet som ett argument när vi anropar funktionen.
Vi kan valfritt skicka ett andra argument, som anger en sökväg att börja från. När vi gör detta, json_each()
behandlar den banan som elementet på toppnivå.
json_each()
funktion leder bara de omedelbara underordnade av arrayen eller objektet på översta nivån, eller bara själva toppnivåelementet om elementet på översta nivån är ett primitivt värde. För att rekursivt gå igenom JSON-understrukturen, använd json_tree()
istället.
Syntax
Vi kan använda funktionen på följande sätt:
json_each(X)
json_each(X,P)
Där X
representerar JSON och P
är ett valfritt argument som representerar sökvägen att behandla som den översta nivån.
Exempel
Här är ett exempel för att visa hur det fungerar:
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 att varje objektmedlem har sin egen rad med lite användbar information, såsom dess typ (SQL-textvärde), sökväg, etc.
Angående id
enligt SQLite-dokumentationen är detta ett internt hushållsnummer, vars beräkning kan ändras i framtida utgåvor. Den enda garantin är att id
kolumnen kommer att vara olika för varje rad.
Den överordnade kolumnen är alltid null
när du anropar json_each()
. Den här kolumnen blir mer meningsfull när du använder json_tree()
.
Array
I det här exemplet är JSON-värdet en array:
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] | $ | +-----+-------+---------+------+----+--------+---------+------+
Ange en sökväg
Vi kan använda ett andra argument för att ange en sökväg som ska behandlas som den översta nivån.
Exempel:
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 det här exemplet kommer vi att använda ett större JSON-dokument. Låt oss först anropa json_each()
utan att ange en sökväg:
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 det här fallet är vårt JSON-värde en array som innehåller tre objekt. Varje objekt listas i resultaten.
Låt oss nu anropa json_each()
igen, men den här gången anger vi en sökväg:
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 det här fallet valde jag det andra matriselementet genom att ange [1]
(matriser är nollbaserade i SQLite).
Resultatet är att utgången innehåller information om det andra arrayelementet.
Den här gången kan vi se att path
kolumnen innehåller $[1]
.
Låt oss gå djupare:
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 rad för varje element i scores
array.
Filtrera frågan
Vi kan modifiera vår fråga för att filtrera resultaten baserat på ett givet kriterium. Till exempel:
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]} | +---------+----------------------------------------------+
Ett databasexempel
Anta att vi har följande tabell:
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"] | +-------+--------------------------------------------------+
Den här tabellen kallas guests
har två kolumner. Den första kolumnen innehåller namnet på gästen, och den andra kolumnen innehåller deras lunchbeställning. De kan beställa tre rätter till lunch. Deras lunchbeställning är i form av en array, där varje rätt är ett element i arrayen.
Här är ett exempel på att köra en fråga som innehåller json_each()
mot denna tabell:
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"] | +-------+-------------------------------------------------+
Här lämnade vi tillbaka alla gäster som beställt äppeljuice till sin lunch, tillsammans med sin fulla lunchbeställning.
Om vi vill returnera alla gäster som beställt äpple "något", kan vi göra så här:
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"] | +-------+-------------------------------------------------+
Lägg märke till att jag använde DISTINCT
klausul i min fråga. Detta säkerställer att vi inte får flera rader returnerade för samma gäst. För att visa vad jag menar, här är frågan igen, men utan 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"] | +-------+-------------------------------------------------+
Den här gången dyker Aisha upp två gånger. Det beror på att hon beställde två äppelrätter till lunch – Äppelpaj och Äppeljuice.