2016-07-09 1 views
5

Je suis bloqué lorsque j'accède à un tableau dans json en utilisant la fonction JSON_VALUE nouvellement introduite. S'il vous plaît considérer le code ci-dessous -Accès à JSON Array dans SQL Server 2016 à l'aide de JSON_VALUE

IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='JsonData') 
    DROP TABLE JsonData; 
go 

CREATE TABLE JsonData(JsonData nvarchar(max)); 
DECLARE @SQL nvarchar(max); 
DECLARE @Table AS TABLE(JsonPath VARCHAR(256)); 

INSERT INTO JsonData(JsonData) 
VALUES(
'{ 
    "firstName": "John", 
    "lastName" : "doe", 
    "age"  : 26, 
    "address" : { 
    "streetAddress": "naist street", 
    "city"   : "Nara", 
    "postalCode" : "630-0192" 
    }, 
    "phoneNumbers": [ 
    { 
     "type" : "iPhone", 
     "number": "0123-4567-8888" 
    }, 
    { 
     "type" : "home", 
     "number": "0123-4567-8910" 
    } 
    ] 
}') 


INSERT INTO @Table 
SELECT VALUE FROM OPENJSON('{ 
"Path1":"$.firstName","Path2":"$.phoneNumbers[:1].number" 
}') ; 

SELECT @SQL=(SELECT 'UNION SELECT '''+ CAST(JsonPath AS VARCHAR(256)) +''',JSON_VALUE(JsonData,'''+a.JsonPath+''') 
        FROM JsonData a'        
        FROM @Table a  
     FOR XML PATH(''), TYPE) 
    .value('.','NVARCHAR(MAX)') 
FROM @Table t; 

SELECT @SQL=RIGHT(@SQL,LEN(@SQL)-5) 

PRINT @SQL  

EXEC SP_EXECUTESQL @SQL; 

ici Si je veux accéder à numéro de téléphone spécifique, syntaxe habituelle d'accéder à ce noeud ne fonctionne pas. J'obtiens l'erreur suivante dans ce cas

JSON path is not properly formatted. Unexpected character ':' is found at position 15. 

Bien que quand je suis arrivé à http://jsonpath.com, je suis en mesure de récupérer la valeur. SQL Server 2016 utilise-t-il une syntaxe différente pour accéder aux valeurs JSON? SQL Server 2016 prend en charge JSON.

+0

Ceci est hors sujet, mais pourrait être utile pour know.You peut utiliser DROP TABLE SI EXISTS JsonData au lieu de si (sélectionnez) drop table .... –

+0

D'accord, les vieilles habitudes meurent dur :-) –

Répondre

4

Pour obtenir tous de phoneNumbers:

DECLARE @json nvarchar(max)= 
    '{ 
     "firstName": "John", 
     "lastName" : "doe", 
     "age"  : 26, 
     "address" : { 
     "streetAddress": "naist street", 
     "city"   : "Nara", 
     "postalCode" : "630-0192" 
     }, 
     "phoneNumbers": [ 
     { 
      "type" : "iPhone", 
      "number": "0123-4567-8888" 
     }, 
     { 
      "type" : "home", 
      "number": "0123-4567-8910" 
     } 
     ] 
    }' 

    SELECT [Type], [Number] 
    FROM OPENJSON(@json, '$.phoneNumbers') 
    WITH ([Type] NVARCHAR(25) '$.type', [Number] NVARCHAR(25) '$.number'); 
+0

Merci encore! Je peux obtenir.Il y aura beaucoup de réglages nécessaires si je ne connais pas la structure exacte de JSON fourni mais vos suggestions m'ont aidé dans la bonne direction.J'ai voulu créer une solution générique.Je souhaite que les futures mises à jour peuvent prendre en charge la traversée JSON correcte. –

2

C'est très similaire, presque identique. Vous ferez votre propre comparaison.

Vous n'avez pas besoin d'utiliser une variable temp @Table puis faire des manipulations ...

il suffit de lancer les requêtes suivantes

SELECT JSON_VALUE(JsonData, '$.phoneNumbers[0].type') AS [PhoneType], 
     JSON_VALUE(JsonData, '$.phoneNumbers[0].number') AS [PhoneNumber] 
FROM JsonData 
WHERE ISJSON(JsonData) > 0; 
--iPhone 0123-4567-8888 

SELECT JSON_VALUE(JsonData, '$.phoneNumbers[1].type') AS [PhoneType], 
     JSON_VALUE(JsonData, '$.phoneNumbers[1].number') AS [PhoneNumber] 
FROM JsonData 
WHERE ISJSON(JsonData) > 0; 
--home 0123-4567-8910 

Découvrez ces liens officiels de Microsoft, sur support JSON pour plus de détails:

https://msdn.microsoft.com/en-us/library/dn921897.aspx

https://msdn.microsoft.com/en-us/library/dn921898.aspx

+0

Salut, Merci pour l'aide! J'avais besoin de la variable @table car ma solution originale nécessite un paramètre dans lequel l'application peut passer n'importe quel chemin JSON. Les données par rapport à ce chemin passé doivent être renvoyées à partir d'un JSON complexe (MUCH). C'est un exemple simplifié et j'ai fondamentalement besoin de retourner tous les éléments si le tableau est fourni en argument. Par exemple, $ .phoneNumbers [:]. Number devrait renvoyer tous les nombres de ce tableau. –

+0

Aham, alors vous êtes très proche de la solution. J'utiliserais les requêtes (ou chemins) ci-dessus dans une requête sql dynamique comme vous essayez dans votre requête. Sachez que $ .phoneNumbers [:] dans T-SQL JSON est en fait $ .phoneNumbers [*] –

+0

Merci encore! J'ai eu une erreur de suivi lorsque j'ai essayé d'utiliser * - Msg 13607, Niveau 16, État 4, Ligne 4 Le chemin JSON n'est pas correctement formaté. Le caractère inattendu '*' se trouve à la position 15. Si vous pouviez me diriger vers un lien expliquant "TSQL JSON" qui serait vraiment utile. Je n'ai pas pu trouver une telle référence –

2

Vous pouvez utiliser « CROSS APPLY » pour obtenir les numéros de téléphone avec prenom:

SELECT JSON_VALUE (jsonData, '$.firstName'),p.* 
    FROM JsonData 
    CROSS APPLY 
    OPENJSON (JsonData, '$.phoneNumbers') WITH(type varchar(10) '$.type', number varchar (30) '$.number') p