Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

JSON_QUERY() vs JSON_VALUE() no SQL Server:Qual é a diferença?


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 tipo nvarchar(max)
  • JSON_VALUE() retorna um valor de texto único do tipo nvarchar(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.