sql >> Base de Datos >  >> RDS >> Sqlserver

JSON_QUERY() vs JSON_VALUE() en SQL Server:¿Cuál es la diferencia?

Dos de las muchas funciones de T-SQL disponibles en SQL Server son JSON_QUERY() y JSON_VALUE() . Estas funciones se pueden utilizar para extraer datos de documentos JSON.

Su sintaxis general es similar y, a primera vista, podría pensar que hacen exactamente lo mismo, pero no es así. Definitivamente hay un lugar para ambas funciones cuando se trabaja con JSON y SQL Server.

Este artículo analiza la diferencia entre JSON_QUERY() y JSON_VALUE() .

La diferencia

Estas dos funciones tienen definiciones ligeramente diferentes, una sintaxis ligeramente diferente y sus valores de retorno son ligeramente diferentes.

Definiciones

Así es como se definen las dos funciones:

JSON_QUERY()
Extrae un objeto o una matriz de una cadena JSON.
JSON_VALUE()
Extrae un valor escalar de una cadena JSON.

Entonces, la diferencia entre estas dos funciones es lo que extraen. Uno extrae un objeto o una matriz, el otro extrae un valor escalar.

Diferencias de sintaxis

Otra diferencia está en la sintaxis:

JSON_QUERY ( expression [ , path ] )
JSON_VALUE ( expression , path )

Mire el JSON_QUERY() sintaxis. Esos corchetes alrededor de la path argumento significa que es un argumento opcional. Eso es porque esta función puede devolver un documento JSON completo si es necesario.

Sin embargo, el argumento de ruta es un argumento requerido cuando se usa JSON_VALUE() función. Por lo tanto, debe proporcionar ambos argumentos al usar esta función.

Valores devueltos

Y una diferencia más está en sus valores de retorno.

  • JSON_QUERY() devuelve un fragmento JSON de tipo nvarchar(max)
  • JSON_VALUE() devuelve un valor de texto único de tipo nvarchar(4000)

Ejemplo 1:extraer un valor escalar

Aquí hay un ejemplo para demostrar la diferencia entre estas funciones al intentar extraer un 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         |
+--------------+--------------+

Entonces, ambas funciones intentan extraer el mismo valor del documento JSON, pero solo una tiene éxito:JSON_VALUE() . Esto se debe a que el valor que intentan extraer es un valor escalar. Básicamente, un valor escalar es una unidad de datos. Podría ser una cadena de texto o un número. Pero no puede ser un objeto o una matriz.

Ejemplo 2:extraer una matriz

En este ejemplo, ambas funciones intentan extraer una matriz completa.

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"] |
+--------------+----------------------------------------+

En este caso, solo el JSON_QUERY() la función tiene éxito.

Ejemplo 3:extraer un elemento de matriz

Este ejemplo es similar al anterior, excepto que en lugar de intentar extraer toda la matriz, solo queremos un elemento de la matriz.

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         |
+--------------+--------------+

Así que esta vez JSON_VALUE() es el ganador.

Ejemplo 4:extraer un objeto

Probemos con un objeto completo.

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"]  
    }              |
+--------------+--------------+

Y JSON_QUERY() gana.

(Disculpe el formato, así es como mi herramienta de línea de comandos MSSQL devuelve los resultados).

Ejemplo 5:extraiga el documento JSON completo

Probemos con todo el 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
        }
    ]
}              |
+--------------+--------------+

Entonces JSON_QUERY() es el único que puede devolver el documento completo.

Ejemplo 6:omitir la ruta

Otra diferencia entre estas dos funciones es que el argumento de ruta es opcional cuando se usa JSON_QUERY() . Si omite esto, se devuelve el documento JSON completo.

No puede omitir este argumento cuando usa JSON_VALUE() , ya que es un argumento requerido. Esto probablemente se deba al hecho de que la función solo puede devolver un valor escalar. Si el primer argumento solo consistiera en un valor escalar, no sería un JSON válido.

De todos modos, aquí hay un ejemplo de cómo omitir el argumento de ruta de JSON_QUERY() :

SELECT JSON_QUERY('{"Name": "Homer"}') AS 'Result';

Resultado:

+-------------------+
| Result            |
|-------------------|
| {"Name": "Homer"} |
+-------------------+

Y esto es lo que sucede si intentamos ese truco con 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).

Ejemplo 7:modo de ruta

En los ejemplos anteriores, cuando una función no podía manejar la ruta proporcionada, devolvía NULL . Esto se debe a que todos esos ejemplos se ejecutaron en modo laxo (el modo predeterminado).

Si los hubiéramos ejecutado en modo estricto, habríamos recibido un error en su lugar. Para especificar explícitamente el modo de ruta, simplemente agréguelo antes del signo de dólar (y deje un espacio entre ellos).

Aquí hay un ejemplo de lo que sucede cuando proporciona una ruta no válida mientras está en modo estricto:

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.