Duas das muitas funções T-SQL disponíveis no SQL Server são
JSON_QUERY()
e JSON_VALUE()
. Essas funções podem ser usadas para extrair dados de documentos JSON. Sua sintaxe geral é semelhante e, à primeira vista, você pode pensar que eles fazem exatamente a mesma coisa, mas não fazem. Definitivamente, há um lugar para ambas as funções ao trabalhar com JSON e SQL Server.
Este artigo analisa a diferença entre
JSON_QUERY()
e JSON_VALUE()
. A diferença
Essas duas funções têm definições ligeiramente diferentes, uma sintaxe ligeiramente diferente e seus valores de retorno são ligeiramente diferentes.
Definições
Veja como as duas funções são definidas:
JSON_QUERY()
- Extrai um objeto ou uma matriz de uma string JSON.
JSON_VALUE()
- Extrai um valor escalar de uma string JSON.
Portanto, a diferença entre essas duas funções é o que elas extraem. Um extrai um objeto ou um array, o outro extrai um valor escalar.
Diferenças de sintaxe
Outra diferença está na sintaxe:
JSON_QUERY ( expression [ , path ] ) JSON_VALUE ( expression , path )
Veja o
JSON_QUERY()
sintaxe. Esses colchetes ao redor do path
argumento significa que é um argumento opcional. Isso porque essa função pode retornar um documento JSON inteiro, se necessário. No entanto, o argumento de caminho é um argumento obrigatório ao usar o
JSON_VALUE()
função. Portanto, você deve fornecer os dois argumentos ao usar esta função. Valores de retorno
E mais uma diferença está em seus valores de retorno.
JSON_QUERY()
retorna um fragmento JSON do tiponvarchar(max)
JSON_VALUE()
retorna um valor de texto único do tiponvarchar(4000)
Exemplo 1 – Extrair um valor escalar
Aqui está um exemplo para demonstrar a diferença entre essas funções ao tentar extrair um valor escalar.
SELECT JSON_VALUE('{"Name": "Homer"}', '$.Name') AS 'JSON_VALUE', JSON_QUERY('{"Name": "Homer"}', '$.Name') AS 'JSON_QUERY';
Resultado:
+--------------+--------------+ | JSON_VALUE | JSON_QUERY | |--------------+--------------| | Homer | NULL | +--------------+--------------+
Portanto, ambas as funções estão tentando extrair o mesmo valor do documento JSON, mas apenas uma consegue:
JSON_VALUE()
. Isso ocorre porque o valor que eles estão tentando extrair é um valor escalar. Basicamente, um valor escalar é uma unidade de dados. Pode ser uma sequência de texto ou um número. Mas não pode ser um objeto ou um array. Exemplo 2 – Extrair uma matriz
Neste exemplo, ambas as funções tentam extrair uma matriz inteira.
DECLARE @data NVARCHAR(4000) SET @data=N'{ "Suspect": { "Name": "Homer Simpson", "Hobbies": ["Eating", "Sleeping", "Base Jumping"] } }' SELECT JSON_VALUE(@data,'$.Suspect.Hobbies') AS 'JSON_VALUE', JSON_QUERY(@data,'$.Suspect.Hobbies') AS 'JSON_QUERY';
Resultado:
+--------------+----------------------------------------+ | JSON_VALUE | JSON_QUERY | |--------------+----------------------------------------| | NULL | ["Eating", "Sleeping", "Base Jumping"] | +--------------+----------------------------------------+
Neste caso, apenas o
JSON_QUERY()
função for bem-sucedida. Exemplo 3 – Extrair um item de matriz
Este exemplo é semelhante ao anterior, exceto que em vez de tentar extrair todo o array, queremos apenas um único item do array.
DECLARE @data NVARCHAR(4000) SET @data=N'{ "Suspect": { "Name": "Homer Simpson", "Hobbies": ["Eating", "Sleeping", "Base Jumping"] } }' SELECT JSON_VALUE(@data,'$.Suspect.Hobbies[2]') AS 'JSON_VALUE', JSON_QUERY(@data,'$.Suspect.Hobbies[2]') AS 'JSON_QUERY';
Resultado:
+--------------+--------------+ | JSON_VALUE | JSON_QUERY | |--------------+--------------| | Base Jumping | NULL | +--------------+--------------+
Desta vez
JSON_VALUE()
é o vencedor. Exemplo 4 – Extrair um objeto
Vamos tentar um objeto inteiro.
DECLARE @data NVARCHAR(4000) SET @data=N'{ "Suspect": { "Name": "Homer Simpson", "Hobbies": ["Eating", "Sleeping", "Base Jumping"] } }' SELECT JSON_VALUE(@data,'$.Suspect') AS 'JSON_VALUE', JSON_QUERY(@data,'$.Suspect') AS 'JSON_QUERY';
Resultado:
+--------------+--------------+ | JSON_VALUE | JSON_QUERY | |--------------+--------------| | NULL | { "Name": "Homer Simpson", "Hobbies": ["Eating", "Sleeping", "Base Jumping"] } | +--------------+--------------+
E
JSON_QUERY()
vitórias. (Desculpe a formatação, é assim que minha ferramenta de linha de comando MSSQL retorna os resultados).
Exemplo 5 – Extraia todo o documento JSON
Vamos tentar para todo o documento JSON.
DECLARE @data NVARCHAR(4000) SET @data=N'{ "Cities": [ { "Name": "Kabul", "CountryCode": "AFG", "District": "Kabol", "Population": 1780000 }, { "Name": "Qandahar", "CountryCode": "AFG", "District": "Qandahar", "Population": 237500 } ] }' SELECT JSON_VALUE(@data, '$') AS 'JSON_VALUE', JSON_QUERY(@data, '$') AS 'JSON_QUERY';
Resultado:
+--------------+--------------+ | JSON_VALUE | JSON_QUERY | |--------------+--------------| | NULL | { "Cities": [ { "Name": "Kabul", "CountryCode": "AFG", "District": "Kabol", "Population": 1780000 }, { "Name": "Qandahar", "CountryCode": "AFG", "District": "Qandahar", "Population": 237500 } ] } | +--------------+--------------+
Então
JSON_QUERY()
é o único que pode retornar o documento inteiro. Exemplo 6 – Omitir o caminho
Outra diferença entre essas duas funções é que o argumento path é opcional ao usar
JSON_QUERY()
. Se você omitir isso, todo o documento JSON será retornado. Você não pode omitir este argumento ao usar
JSON_VALUE()
, pois é um argumento obrigatório. Isso provavelmente se deve ao fato de que a função só pode retornar um valor escalar. Se o primeiro argumento consistisse apenas em um valor escalar, não seria um JSON válido. De qualquer forma, aqui está um exemplo de omissão do argumento path de
JSON_QUERY()
:SELECT JSON_QUERY('{"Name": "Homer"}') AS 'Result';
Resultado:
+-------------------+ | Result | |-------------------| | {"Name": "Homer"} | +-------------------+
E aqui está o que acontece se tentarmos esse truque com
JSON_VALUE()
:SELECT JSON_VALUE('{"Name": "Homer"}') AS 'Result';
Resultado:
Msg 174, Level 15, State 1, Line 1 The json_value function requires 2 argument(s).
Exemplo 7 – Modo de caminho
Nos exemplos anteriores, quando uma função não conseguia lidar com o caminho fornecido, ela retornava
NULL
. Isso ocorre porque todos esses exemplos foram executados no modo lax (o modo padrão). Se os executássemos no modo estrito, teríamos recebido um erro. Para especificar explicitamente o modo de caminho, basta adicioná-lo antes do cifrão (e deixar um espaço entre eles).
Aqui está um exemplo do que acontece quando você fornece um caminho inválido no modo estrito:
SELECT JSON_VALUE('{"Name": "Homer"}', 'strict $.Name') AS 'JSON_VALUE', JSON_QUERY('{"Name": "Homer"}', 'strict $.Name') AS 'JSON_QUERY';
Resultado:
Msg 13624, Level 16, State 2, Line 1 Object or array cannot be found in the specified JSON path.