Dans SQLite, json_each()
est une fonction table qui parcourt la valeur JSON fournie comme premier argument et renvoie une table composée d'une ligne pour chaque élément de tableau ou membre d'objet.
Nous fournissons la valeur JSON comme argument lorsque nous appelons la fonction.
Nous pouvons éventuellement passer un deuxième argument, qui spécifie un chemin à partir duquel commencer. Lorsque nous faisons cela, json_each()
traite ce chemin comme l'élément de niveau supérieur.
Le json_each()
La fonction parcourt uniquement les enfants immédiats du tableau ou de l'objet de niveau supérieur, ou uniquement l'élément de niveau supérieur lui-même si l'élément de niveau supérieur est une valeur primitive. Pour parcourir de manière récursive la sous-structure JSON, utilisez json_tree()
à la place.
Syntaxe
Nous pouvons utiliser la fonction des manières suivantes :
json_each(X)
json_each(X,P)
Où X
représente le JSON, et P
est un argument facultatif qui représente le chemin à traiter comme le niveau supérieur.
Exemple
Voici un exemple pour montrer comment cela fonctionne :
SELECT * FROM json_each('{ "name" : "Woof", "age" : 10 }');
Résultat :
+------+-------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+---------+------+----+--------+---------+------+ | name | Woof | text | Woof | 2 | null | $.name | $ | | age | 10 | integer | 10 | 4 | null | $.age | $ | +------+-------+---------+------+----+--------+---------+------+
Nous pouvons voir que chaque membre de l'objet a sa propre ligne avec des informations utiles, telles que son type (valeur de texte SQL), son chemin, etc.
Concernant l'id
colonne, selon la documentation SQLite, il s'agit d'un numéro de gestion interne, dont le calcul pourrait changer dans les versions futures. La seule garantie est que le id
la colonne sera différente pour chaque ligne.
La colonne parent est toujours null
lors de l'appel de json_each()
. Cette colonne devient plus significative lors de l'utilisation de json_tree()
.
Tableau
Dans cet exemple, la valeur JSON est un tableau :
SELECT * FROM json_each('[ 10, 30, 45 ]');
Résultat :
+-----+-------+---------+------+----+--------+---------+------+ | 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] | $ | +-----+-------+---------+------+----+--------+---------+------+
Spécifier un chemin
Nous pouvons utiliser un deuxième argument pour spécifier un chemin à traiter comme le niveau supérieur.
Exemple :
SELECT * FROM json_each('{ "a" : 1, "b" : [ 4, 7, 8 ] }', '$.b');
Résultat :
+-----+-------+---------+------+----+--------+---------+------+ | 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 | +-----+-------+---------+------+----+--------+---------+------+
Document plus grand
Dans cet exemple, nous utiliserons un document JSON plus volumineux. Appelons d'abord json_each()
sans spécifier de chemin :
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 ]
}
]'
);
Résultat :
+-----+----------------------------------------------+--------+------+----+--------+---------+------+ | 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] | $ | +-----+----------------------------------------------+--------+------+----+--------+---------+------+
Dans ce cas, notre valeur JSON est un tableau qui contient trois objets. Chaque objet est listé dans les résultats.
Maintenant, appelons json_each()
encore une fois, mais cette fois nous allons spécifier un chemin :
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]'
);
Résultat :
+--------+------------+---------+------+----+--------+-------------+------+ | 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] | +--------+------------+---------+------+----+--------+-------------+------+
Dans ce cas, j'ai choisi le deuxième élément du tableau en spécifiant [1]
(les tableaux sont basés sur zéro dans SQLite).
Le résultat est que la sortie contient des informations sur le deuxième élément du tableau.
Cette fois, nous pouvons voir que le path
la colonne contient $[1]
.
Allons plus loin :
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'
);
Résultat :
+-----+-------+---------+------+----+--------+----------------+-------------+ | 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 | +-----+-------+---------+------+----+--------+----------------+-------------+
Nous obtenons maintenant une ligne pour chaque élément dans les scores
tableau.
Filtrer la requête
Nous pouvons modifier notre requête pour filtrer les résultats en fonction d'un critère donné. Par exemple :
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%';
Résultat :
+---------+----------------------------------------------+ | fullkey | value | +---------+----------------------------------------------+ | $[1] | {"user":"Faye","age":25,"scores":[90,87,93]} | +---------+----------------------------------------------+
Un exemple de base de données
Supposons que nous ayons le tableau suivant :
SELECT * FROM guests;
Résultat :
+-------+--------------------------------------------------+ | 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"] | +-------+--------------------------------------------------+
Cette table appelée guests
a deux colonnes. La première colonne contient le nom de l'invité et la deuxième colonne contient sa commande de déjeuner. Ils peuvent commander trois plats pour le déjeuner. Leur commande de déjeuner se présente sous la forme d'un tableau, où chaque plat est un élément du tableau.
Voici un exemple d'exécution d'une requête qui incorpore json_each()
contre ce tableau :
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple Juice';
Résultat :
+-------+-------------------------------------------------+ | guest | lunch | +-------+-------------------------------------------------+ | Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"] | | Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | +-------+-------------------------------------------------+
Ici, nous avons renvoyé tous les invités qui ont commandé du jus de pomme avec leur déjeuner, ainsi que leur commande de déjeuner complète.
Si nous voulons renvoyer tous les invités qui ont commandé un « quelque chose » à la pomme, nous pouvons procéder comme suit :
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Résultat :
+-------+-------------------------------------------------+ | 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"] | +-------+-------------------------------------------------+
Notez que j'ai utilisé le DISTINCT
clause dans ma requête. Cela garantit que nous n'obtenons pas plusieurs lignes renvoyées pour le même invité. Pour illustrer ce que je veux dire, voici à nouveau la requête, mais sans le DISTINCT
clause :
SELECT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Résultat :
+-------+-------------------------------------------------+ | 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"] | +-------+-------------------------------------------------+
Cette fois, Aisha apparaît deux fois. C'est parce qu'elle a commandé deux plats à base de pommes pour le déjeuner :une tarte aux pommes et un jus de pomme.