Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

JSON_QUERY() vs JSON_VALUE() dans SQL Server :Quelle est la différence ?

Deux des nombreuses fonctions T-SQL disponibles dans SQL Server sont JSON_QUERY() et JSON_VALUE() . Ces fonctions peuvent être utilisées pour extraire des données de documents JSON.

Leur syntaxe générale est similaire, et à première vue, vous pourriez penser qu'ils font exactement la même chose, mais ce n'est pas le cas. Il y a certainement une place pour les deux fonctions lorsque vous travaillez avec JSON et SQL Server.

Cet article examine la différence entre JSON_QUERY() et JSON_VALUE() .

La différence

Ces deux fonctions ont des définitions légèrement différentes, une syntaxe légèrement différente et leurs valeurs de retour sont légèrement différentes.

Définitions

Voici comment les deux fonctions sont définies :

JSON_QUERY()
Extrait un objet ou un tableau d'une chaîne JSON.
JSON_VALUE()
Extrait une valeur scalaire d'une chaîne JSON.

La différence entre ces deux fonctions est donc ce qu'elles extraient. L'un extrait un objet ou un tableau, l'autre extrait une valeur scalaire.

Différences de syntaxe

Une autre différence réside dans la syntaxe :

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

Regardez le JSON_QUERY() syntaxe. Ces crochets autour du path signifie qu'il s'agit d'un argument facultatif. En effet, cette fonction peut renvoyer un document JSON entier si nécessaire.

Cependant, l'argument path est un argument obligatoire lors de l'utilisation de JSON_VALUE() une fonction. Vous devez donc fournir les deux arguments lorsque vous utilisez cette fonction.

Valeurs de retour

Et une autre différence réside dans leurs valeurs de retour.

  • JSON_QUERY() renvoie un fragment JSON de type nvarchar(max)
  • JSON_VALUE() renvoie une seule valeur de texte de type nvarchar(4000)

Exemple 1 - Extraire une valeur scalaire

Voici un exemple pour démontrer la différence entre ces fonctions lorsque vous essayez d'extraire une valeur scalaire.

SELECT 
  JSON_VALUE('{"Name": "Homer"}', '$.Name') AS 'JSON_VALUE',
  JSON_QUERY('{"Name": "Homer"}', '$.Name') AS 'JSON_QUERY';

Résultat :

+--------------+--------------+
| JSON_VALUE   | JSON_QUERY   |
|--------------+--------------|
| Homer        | NULL         |
+--------------+--------------+

Les deux fonctions essaient donc d'extraire la même valeur du document JSON, mais une seule réussit :JSON_VALUE() . C'est parce que la valeur qu'ils essaient d'extraire est une valeur scalaire. Fondamentalement, une valeur scalaire est une unité de données. Il peut s'agir d'une chaîne de texte ou d'un nombre. Mais il ne peut pas s'agir d'un objet ou d'un tableau.

Exemple 2 – Extraire un tableau

Dans cet exemple, les deux fonctions essaient d'extraire un tableau entier.

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';

Résultat :

+--------------+----------------------------------------+
| JSON_VALUE   | JSON_QUERY                             |
|--------------+----------------------------------------|
| NULL         | ["Eating", "Sleeping", "Base Jumping"] |
+--------------+----------------------------------------+

Dans ce cas, seul le JSON_QUERY() la fonction réussit.

Exemple 3 - Extraire un élément de tableau

Cet exemple est similaire au précédent, sauf qu'au lieu d'essayer d'extraire tout le tableau, nous ne voulons qu'un seul élément du tableau.

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';

Résultat :

+--------------+--------------+
| JSON_VALUE   | JSON_QUERY   |
|--------------+--------------|
| Base Jumping | NULL         |
+--------------+--------------+

Donc cette fois JSON_VALUE() est le gagnant.

Exemple 4 - Extraire un objet

Essayons pour un objet entier.

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';

Résultat :

+--------------+--------------+
| JSON_VALUE   | JSON_QUERY   |
|--------------+--------------|
| NULL         | {    
       "Name": "Homer Simpson",
       "Hobbies": ["Eating", "Sleeping", "Base Jumping"]  
    }              |
+--------------+--------------+

Et JSON_QUERY() gagne.

(Excusez le formatage, c'est ainsi que mon outil de ligne de commande MSSQL renvoie les résultats).

Exemple 5 - Extraire l'intégralité du document JSON

Essayons pour l'ensemble du document 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';

Résultat :

+--------------+--------------+
| JSON_VALUE   | JSON_QUERY   |
|--------------+--------------|
| NULL         | {
    "Cities": [
        {
            "Name": "Kabul",
            "CountryCode": "AFG",
            "District": "Kabol",
            "Population": 1780000
        },
        {
            "Name": "Qandahar",
            "CountryCode": "AFG",
            "District": "Qandahar",
            "Population": 237500
        }
    ]
}              |
+--------------+--------------+

Donc JSON_QUERY() est le seul qui peut retourner le document entier.

Exemple 6 - Omettre le chemin

Une autre différence entre ces deux fonctions est que l'argument path est facultatif lors de l'utilisation de JSON_QUERY() . Si vous l'omettez, tout le document JSON est renvoyé.

Vous ne pouvez pas omettre cet argument lors de l'utilisation de JSON_VALUE() , car il s'agit d'un argument obligatoire. Cela est probablement dû au fait que la fonction ne peut renvoyer qu'une valeur scalaire. Si le premier argument ne consistait qu'en une valeur scalaire, ce ne serait pas un JSON valide.

Quoi qu'il en soit, voici un exemple d'omission de l'argument path de JSON_QUERY() :

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

Résultat :

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

Et voici ce qui se passe si nous essayons cette astuce avec JSON_VALUE() :

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

Résultat :

Msg 174, Level 15, State 1, Line 1
The json_value function requires 2 argument(s).

Exemple 7 - Mode Chemin

Dans les exemples précédents, lorsqu'une fonction ne pouvait pas gérer le chemin fourni, elle retournait NULL . En effet, tous ces exemples ont été exécutés en mode laxiste (le mode par défaut).

Si nous les avions exécutés en mode strict, nous aurions reçu une erreur à la place. Pour spécifier explicitement le mode de chemin, ajoutez-le simplement avant le signe dollar (et laissez un espace entre eux).

Voici un exemple de ce qui se passe lorsque vous fournissez un chemin non valide en mode strict :

SELECT 
  JSON_VALUE('{"Name": "Homer"}', 'strict $.Name') AS 'JSON_VALUE',
  JSON_QUERY('{"Name": "Homer"}', 'strict $.Name') AS 'JSON_QUERY';

Résultat :

Msg 13624, Level 16, State 2, Line 1
Object or array cannot be found in the specified JSON path.