Convalidare, eseguire query e modificare i dati JSON con funzioni predefinite (SQL Server)
Si applica a: SQL Server 2016 (13.x) e alle sue versioni successive Database SQL di Azure Istanza gestita di SQL di Azure
Il supporto integrato per JSON include le funzioni predefinite seguenti descritte brevemente in questo articolo.
- ISJSON verifica se una stringa include contenuto JSON valido.
- JSON_VALUE estrae un valore scalare da una stringa JSON.
- JSON_QUERY estrae un oggetto o una matrice da una stringa JSON.
- JSON_MODIFY aggiorna il valore di una proprietà in una stringa JSON e restituisce la stringa JSON aggiornata.
Per tutte le funzioni JSON, vedere Funzioni JSON.
Gli esempi di codice Transact-SQL in questo articolo utilizzano il database campione AdventureWorks2022
o AdventureWorksDW2022
, che si possono scaricare dalla pagina iniziale: Esempi di Microsoft SQL Server e progetti della community.
Testo JSON per gli esempi in questa pagina
Gli esempi in questa pagina usano il testo JSON simile al contenuto illustrato nell'esempio seguente:
{
"id": "DesaiFamily",
"parents": [
{ "familyName": "Desai", "givenName": "Prashanth" },
{ "familyName": "Miller", "givenName": "Helen" }
],
"children": [
{
"familyName": "Desai",
"givenName": "Jesse",
"gender": "female",
"grade": 1,
"pets": [
{ "givenName": "Goofy" },
{ "givenName": "Shadow" }
]
},
{
"familyName": "Desai",
"givenName": "Lisa",
"gender": "female",
"grade": 8
}
],
"address": {
"state": "NY",
"county": "Manhattan",
"city": "NY"
},
"creationDate": 1431620462,
"isRegistered": false
}
Questo documento JSON, che contiene elementi complessi annidati, viene archiviato nella tabella di esempio seguente:
CREATE TABLE Families (
id INT identity CONSTRAINT PK_JSON_ID PRIMARY KEY,
[doc] NVARCHAR(MAX)
);
Le funzioni JSON funzionano allo stesso modo se il documento JSON viene archiviato in varchar, nvarchar o nel tipo di dati json nativo.
Convalidare il testo JSON tramite la funzione ISJSON
La funzione ISJSON
verifica se una stringa include contenuto JSON valido.
L'esempio seguente restituisce le righe in cui la colonna JSON include testo JSON valido. Senza un vincolo JSON esplicito, è possibile immettere qualsiasi testo nella colonna nvarchar:
SELECT *
FROM Families
WHERE ISJSON(doc) > 0;
Per ulteriori informazioni, vedere ISJSON.
Estrarre un valore dal testo JSON tramite la funzione JSON_VALUE
La funzione JSON_VALUE
estrae un valore scalare da una stringa JSON. La query seguente restituisce i documenti in cui il campo JSON id
corrisponde al valore DesaiFamily
, ordinati in base ai campi JSON city
e state
:
SELECT JSON_VALUE(f.doc, '$.id') AS Name,
JSON_VALUE(f.doc, '$.address.city') AS City,
JSON_VALUE(f.doc, '$.address.county') AS County
FROM Families f
WHERE JSON_VALUE(f.doc, '$.id') = N'DesaiFamily'
ORDER BY JSON_VALUE(f.doc, '$.address.city') DESC,
JSON_VALUE(f.doc, '$.address.state') ASC
I risultati di questa query sono riportati nella tabella seguente:
Nome | Città | Contea |
---|---|---|
DesaiFamily |
NY |
Manhattan |
Per altre informazioni, vedere JSON_VALUE.
Estrarre un oggetto o una matrice dal testo JSON tramite la funzione JSON_QUERY
La funzione JSON_QUERY
estrae un oggetto o una matrice da una stringa JSON. Nell'esempio seguente viene illustrato come restituire un frammento JSON nei risultati della query.
SELECT JSON_QUERY(f.doc, '$.address') AS Address,
JSON_QUERY(f.doc, '$.parents') AS Parents,
JSON_QUERY(f.doc, '$.parents[0]') AS Parent0
FROM Families f
WHERE JSON_VALUE(f.doc, '$.id') = N'DesaiFamily';
I risultati di questa query sono riportati nella tabella seguente:
Address | Principali | Parent0 |
---|---|---|
{ "state": "NY", "county": "Manhattan", "city": "NY" } |
[ { "familyName": "Desai", "givenName": "Prashanth" }, { "familyName": "Miller", "givenName": "Helen" } ] |
{ "familyName": "Desai", "givenName": "Prashanth" } |
Per altre informazioni, vedere JSON_QUERY.
Analizzare raccolte JSON annidate
La funzione OPENJSON
consente di trasformare la sottomatrice JSON nel set di righe e quindi di unirla in join all'elemento padre. È ad esempio possibile restituire tutti i documenti della famiglia e "unirli in join" ai relativi oggetti children
archiviati come una matrice JSON interna:
SELECT JSON_VALUE(f.doc, '$.id') AS Name,
JSON_VALUE(f.doc, '$.address.city') AS City,
c.givenName,
c.grade
FROM Families f
CROSS APPLY OPENJSON(f.doc, '$.children') WITH (
grade INT,
givenName NVARCHAR(100)
) c
I risultati di questa query sono riportati nella tabella seguente:
Nome | Città | givenName | grade |
---|---|---|---|
DesaiFamily |
NY |
Jesse |
1 |
DesaiFamily |
NY |
Lisa |
8 |
Si ottengono due righe come risultato perché una riga padre viene unita in join con due righe figlio generate analizzando due elementi della sottomatrice degli elementi figlio. La funzione OPENJSON
analizza il frammento children
dalla colonna doc
e restituisce grade
e givenName
da ogni elemento come set di righe. Questo set di righe può essere unito in join al documento padre.
Eseguire query in sottomatrici JSON gerarchiche annidate
È possibile applicare più chiamate CROSS APPLY OPENJSON
per eseguire query in strutture JSON annidate. Il documento JSON usato in questo esempio include una matrice annidata denominata children
, in cui ogni elemento figlio ha una matrice annidata di pets
. La query seguente analizza gli elementi figlio di ogni documento, restituirà ogni oggetto della matrice come riga e quindi analizzerà la matrice pets
:
SELECT c.familyName,
c.givenName AS childGivenName,
p.givenName AS petName
FROM Families f
CROSS APPLY OPENJSON(f.doc) WITH (
familyName NVARCHAR(100),
children NVARCHAR(MAX) AS JSON
) AS a
CROSS APPLY OPENJSON(children) WITH (
familyName NVARCHAR(100),
givenName NVARCHAR(100),
pets NVARCHAR(max) AS JSON
) AS c
OUTER APPLY OPENJSON(pets) WITH (givenName NVARCHAR(100)) AS p;
La prima chiamata di OPENJSON
restituisce un frammento della matrice children
usando la clausola AS JSON. Questo frammento di matrice viene fornito alla seconda funzione OPENJSON
che restituisce givenName
, firstName
di ogni figlio, nonché la matrice di pets
. La matrice di pets
viene fornita alla terza funzione OPENJSON
che restituisce givenName
l'animale domestico.
I risultati di questa query sono riportati nella tabella seguente:
familyName | childGivenName | petName |
---|---|---|
Desai |
Jesse |
Goofy |
Desai |
Jesse |
Shadow |
Desai |
Lisa |
NULL |
Il documento radice viene unito in join alle due righe children
restituite dalla prima chiamata di OPENJSON(children)
che crea due righe (o tuple). Ogni riga viene quindi unita in join alle nuove righe generate da OPENJSON(pets)
tramite l'operatore OUTER APPLY
. Jesse ha due animali domestici, quindi (Desai, Jesse)
viene unito in join alle due righe generate per Goofy
e Shadow
. Lisa non ha animali domestici, quindi non sono presenti righe restituite da OPENJSON(pets)
per questa tupla. Tuttavia, dal momento che si usa OUTER APPLY
, si ottiene NULL
nella colonna. Specificando CROSS APPLY
invece di OUTER APPLY
, Lisa non verrebbe inclusa nel risultato perché non sono presenti righe di animali domestici che possono essere unite in join con questa tupla.
Confronto tra JSON_VALUE e JSON_QUERY
La differenza principale tra JSON_VALUE
e JSON_QUERY
consiste nel fatto che JSON_VALUE
restituisce un valore scalare, mentre JSON_QUERY
restituisce un oggetto o una matrice.
Si consideri il testo JSON di esempio seguente.
{
"a": "[1,2]",
"b": [1, 2],
"c": "hi"
}
In questo testo JSON di esempio i membri dati "a" e "c" sono valori stringa, mentre il membro dati "b" è una matrice. JSON_VALUE
e JSON_QUERY
restituiscono i risultati seguenti:
Percorso | Valori restituiti JSON_VALUE |
Valori restituiti JSON_QUERY |
---|---|---|
$ |
NULL o errore |
{ "a": "[1,2]", "b": [1, 2], "c": "hi" } |
$.a |
[1,2] |
NULL o errore |
$.b |
NULL o errore |
[1,2] |
$.b[0] |
1 |
NULL o errore |
$.c |
hi |
NULL o errore |
Test di JSON_VALUE e JSON_QUERY con il database di esempio AdventureWorks
Testare le funzioni predefinite descritte in questo argomento eseguendo gli esempi seguenti con il database di esempio AdventureWorks2022
. Per maggiori informazioni su come aggiungere i dati JSON per il testing eseguendo uno script, vedere Test drive del supporto JSON integrato.
Negli esempi seguenti la colonna Info
nella tabella SalesOrder_json
contiene testo JSON.
Esempio 1: restituire colonne standard e dati JSON
La query seguente restituisce valori sia dalle colonne relazionali standard sia da una colonna JSON.
SELECT SalesOrderNumber,
OrderDate,
Status,
ShipDate,
AccountNumber,
TotalDue,
JSON_QUERY(Info, '$.ShippingInfo') ShippingInfo,
JSON_QUERY(Info, '$.BillingInfo') BillingInfo,
JSON_VALUE(Info, '$.SalesPerson.Name') SalesPerson,
JSON_VALUE(Info, '$.ShippingInfo.City') City,
JSON_VALUE(Info, '$.Customer.Name') Customer,
JSON_QUERY(OrderItems, '$') OrderItems
FROM Sales.SalesOrder_json
WHERE ISJSON(Info) > 0;
Esempio 2: aggregare e filtrare valori JSON
La query seguente aggrega i subtotali in base al nome del cliente (archiviato in JSON) e in base allo stato (archiviato in una colonna normale), quindi filtra i risultati in base alla città (archiviata in JSON) e in base al valore OrderDate (archiviato in una colonna normale).
DECLARE @territoryid INT;
DECLARE @city NVARCHAR(32);
SET @territoryid = 3;
SET @city = N'Seattle';
SELECT JSON_VALUE(Info, '$.Customer.Name') AS Customer,
Status,
SUM(SubTotal) AS Total
FROM Sales.SalesOrder_json
WHERE TerritoryID = @territoryid
AND JSON_VALUE(Info, '$.ShippingInfo.City') = @city
AND OrderDate > '1/1/2015'
GROUP BY JSON_VALUE(Info, '$.Customer.Name'),
Status
HAVING SUM(SubTotal) > 1000;
Aggiornare i valori delle proprietà in testo JSON tramite la funzione JSON_MODIFY
La funzione JSON_MODIFY
aggiorna il valore di una proprietà in una stringa JSON e restituisce la stringa JSON aggiornata.
Nell'esempio seguente viene aggiornato il valore di una proprietà JSON in una variabile che include contenuto JSON.
SET @info = JSON_MODIFY(@jsonInfo, '$.info.address[0].town', 'London');
Per altre informazioni, vedere JSON_MODIFY.