No SQLite, json_each()
é uma função com valor de tabela que percorre o valor JSON fornecido como seu primeiro argumento e retorna uma tabela que consiste em uma linha para cada elemento da matriz ou membro do objeto.
Fornecemos o valor JSON como um argumento quando chamamos a função.
Opcionalmente, podemos passar um segundo argumento, que especifica um caminho para começar. Quando fazemos isso, json_each()
trata esse caminho como o elemento de nível superior.
O json_each()
A função apenas percorre os filhos imediatos do array ou objeto de nível superior, ou apenas o próprio elemento de nível superior se o elemento de nível superior for um valor primitivo. Para percorrer recursivamente a subestrutura JSON, use json_tree()
em vez de.
Sintaxe
Podemos usar a função das seguintes maneiras:
json_each(X)
json_each(X,P)
Onde X
representa o JSON e P
é um argumento opcional que representa o caminho a ser tratado como o nível superior.
Exemplo
Aqui está um exemplo para demonstrar como funciona:
SELECT * FROM json_each('{ "name" : "Woof", "age" : 10 }');
Resultado:
+------+-------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+---------+------+----+--------+---------+------+ | name | Woof | text | Woof | 2 | null | $.name | $ | | age | 10 | integer | 10 | 4 | null | $.age | $ | +------+-------+---------+------+----+--------+---------+------+
Podemos ver que cada membro do objeto possui sua própria linha com algumas informações úteis, como seu tipo (valor do texto SQL), caminho, etc.
Em relação ao
id
coluna, de acordo com a documentação do SQLite, este é um número interno de manutenção, cujo cálculo pode mudar em versões futuras. A única garantia é que o id
coluna será diferente para cada linha. A coluna pai é sempre
null
ao chamar json_each()
. Esta coluna se torna mais significativa ao usar json_tree()
. Matriz
Neste exemplo, o valor JSON é uma matriz:
SELECT * FROM json_each('[ 10, 30, 45 ]');
Resultado:
+-----+-------+---------+------+----+--------+---------+------+ | 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] | $ | +-----+-------+---------+------+----+--------+---------+------+
Especifique um caminho
Podemos usar um segundo argumento para especificar um caminho para tratar como o nível superior.
Exemplo:
SELECT * FROM json_each('{ "a" : 1, "b" : [ 4, 7, 8 ] }', '$.b');
Resultado:
+-----+-------+---------+------+----+--------+---------+------+ | 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 | +-----+-------+---------+------+----+--------+---------+------+
Documento maior
Neste exemplo, usaremos um documento JSON maior. Primeiro, vamos chamar
json_each()
sem especificar um caminho: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 ]
}
]'
);
Resultado:
+-----+----------------------------------------------+--------+------+----+--------+---------+------+ | 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] | $ | +-----+----------------------------------------------+--------+------+----+--------+---------+------+
Nesse caso, nosso valor JSON é um array que contém três objetos. Cada objeto é listado nos resultados.
Agora, vamos chamar
json_each()
novamente, mas desta vez vamos especificar um caminho: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]'
);
Resultado:
+--------+------------+---------+------+----+--------+-------------+------+ | 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] | +--------+------------+---------+------+----+--------+-------------+------+
Neste caso eu escolhi o segundo elemento do array especificando
[1]
(matrizes são zero com base em SQLite). O resultado é que a saída contém informações sobre o segundo elemento da matriz.
Desta vez podemos ver que o
path
coluna contém $[1]
. Vamos mais fundo:
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'
);
Resultado:
+-----+-------+---------+------+----+--------+----------------+-------------+ | 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 | +-----+-------+---------+------+----+--------+----------------+-------------+
Agora temos uma linha para cada elemento nas
scores
variedade. Filtrando a consulta
Podemos modificar nossa consulta para filtrar os resultados com base em um determinado critério. Por exemplo:
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%';
Resultado:
+---------+----------------------------------------------+ | fullkey | value | +---------+----------------------------------------------+ | $[1] | {"user":"Faye","age":25,"scores":[90,87,93]} | +---------+----------------------------------------------+
Um exemplo de banco de dados
Suponha que temos a seguinte tabela:
SELECT * FROM guests;
Resultado:
+-------+--------------------------------------------------+ | 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"] | +-------+--------------------------------------------------+
Esta tabela chamada
guests
tem duas colunas. A primeira coluna contém o nome do convidado e a segunda coluna contém o pedido do almoço. Eles podem pedir três pratos para o almoço. Seu pedido de almoço está na forma de uma matriz, onde cada prato é um elemento da matriz. Aqui está um exemplo de execução de uma consulta que incorpora
json_each()
contra esta tabela:SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple Juice';
Resultado:
+-------+-------------------------------------------------+ | guest | lunch | +-------+-------------------------------------------------+ | Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"] | | Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | +-------+-------------------------------------------------+
Aqui, devolvemos todos os convidados que pediram suco de maçã com o almoço, junto com o pedido completo do almoço.
Se quisermos devolver todos os convidados que pediram “algo” de maçã, podemos fazer isso:
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Resultado:
+-------+-------------------------------------------------+ | 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"] | +-------+-------------------------------------------------+
Observe que usei o
DISTINCT
cláusula na minha consulta. Isso garante que não recebamos várias linhas retornadas para o mesmo convidado. Para demonstrar o que quero dizer, aqui está a consulta novamente, mas sem o DISTINCT
cláusula:SELECT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Resultado:
+-------+-------------------------------------------------+ | 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"] | +-------+-------------------------------------------------+
Desta vez Aisha aparece duas vezes. Isso porque ela pediu dois pratos de maçã para o almoço – torta de maçã e suco de maçã.