Freigeben über


Überprüfen, Abfragen und Ändern von JSON-Daten mit integrierten Funktionen (SQL Server)

Gilt für: SQL Server 2016 (13.x) und höher Azure SQL-Datenbank Azure SQL Managed Instance

Die integrierte Unterstützung für JSON umfasst die folgenden integrierten Funktionen, die in diesem Artikel kurz beschrieben werden.

  • ISJSON testet, ob eine Zeichenfolge gültiges JSON enthält.
  • JSON_VALUE extrahiert einen skalaren Wert aus einer JSON-Zeichenfolge.
  • JSON_QUERY extrahiert ein Objekt oder ein Array aus einer JSON-Zeichenfolge.
  • JSON_MODIFY aktualisiert den Wert einer Eigenschaft in einer JSON-Zeichenfolge und gibt die aktualisierte JSON-Zeichenfolge zurück.

Informationen zu allen JSON-Funktionen finden Sie unter JSON-Funktionen.

Die Transact-SQL-Codebeispiele in diesem Artikel verwenden die AdventureWorks2022- oder AdventureWorksDW2022-Beispieldatenbank, die Sie von der Homepage Microsoft SQL Server Samples and Community Projects herunterladen können.

JSON-Text für die Beispiele auf dieser Seite

In den Beispielen auf dieser Seite wird der JSON-Text verwendet, der dem im folgenden Beispiel gezeigten Inhalt ähnelt:

{
    "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
}

Dieses JSON-Dokument, das geschachtelte komplexe Elemente enthält, wird in der folgenden Beispieltabelle gespeichert:

CREATE TABLE Families (
    id INT identity CONSTRAINT PK_JSON_ID PRIMARY KEY,
    [doc] NVARCHAR(MAX)
);

JSON-Funktionen funktionieren gleich, unabhängig davon, ob das JSON-Dokument in varchar, nvarchar oder dem nativen json-Datentyp gespeichert ist.

Überprüfen von JSON-Text mithilfe der ISJSON-Funktion

Die ISJSON-Funktion testet, ob eine Zeichenfolge gültiges JSON enthält.

Im folgenden Beispiel werden die Spalten zurückgegeben, in denen die JSON-Spalte einen gültigen JSON-Text enthält. Ohne explizite JSON-Beschränkung können Sie jeden beliebigen Text in der nvarchar-Spalte eingeben:

SELECT *
FROM Families
WHERE ISJSON(doc) > 0;

Weitere Informationen finden Sie unter ISJSON.

Extrahieren eines Wertes aus JSON-Text mithilfe der JSON_VALUE-Funktion

Die JSON_VALUE-Funktion extrahiert einen skalaren Wert aus einer JSON-Zeichenfolge. Die folgende Abfrage gibt die Dokumente zurück, in denen das JSON-Feld id mit dem Wert DesaiFamily übereinstimmt, sortiert nach den JSON-Feldern city und 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

Die Ergebnisse dieser Abfrage sind in der folgenden Tabelle aufgeführt:

Name City Verwaltungsbezirk
DesaiFamily NY Manhattan

Weitere Informationen finden Sie unter JSON_VALUE.

Extrahieren eines Objekts oder eines Arrays aus JSON-Text mithilfe der JSON_QUERY-Funktion

Die JSON_QUERY-Funktion extrahiert ein Objekt oder ein Array aus einer JSON-Zeichenfolge. Im folgenden Beispiel wird gezeigt, wie ein JSON-Fragment in den Abfrageergebnissen zurückgegeben wird.

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

Die Ergebnisse dieser Abfrage sind in der folgenden Tabelle aufgeführt:

Adresse Übergeordnete Elemente (Parents) Übergeordnetes Element 0 (Parent0)
{ "state": "NY", "county": "Manhattan", "city": "NY" } [ { "familyName": "Desai", "givenName": "Prashanth" }, { "familyName": "Miller", "givenName": "Helen" } ] { "familyName": "Desai", "givenName": "Prashanth" }

Weitere Informationen finden Sie unter JSON_QUERY.

Analysieren geschachtelter JSON-Sammlungen

Mit der OPENJSON-Funktion können Sie das JSON-Subarray in das Rowset umwandeln und dann mit dem übergeordneten Element verknüpfen. Als Beispiel können Sie alle Familiendokumente zurückgeben und sie mit ihren children-Objekten „verknüpfen“, die als inneres JSON-Array gespeichert sind:

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

Die Ergebnisse dieser Abfrage sind in der folgenden Tabelle aufgeführt:

Name Ort givenName Klasse
DesaiFamily NY Jesse 1
DesaiFamily NY Lisa 8

Das Ergebnis sind zwei Zeilen, da eine übergeordnete Zeile mit zwei untergeordneten Zeilen verbunden ist, die durch das Analysieren von zwei Elementen des untergeordneten Subarrays erzeugt werden. Die OPENJSON-Funktion analysiert children-Fragmente aus der Spalte doc und gibt grade und givenName von jedem Element als Zeilen zurück. Dieses Rowset kann mit dem übergeordneten Dokument verknüpft werden.

Abfragen geschachtelter hierarchischer JSON-Subarrays

Sie können mehrere CROSS APPLY OPENJSON-Aufrufe anwenden, um geschachtelte JSON-Strukturen abzufragen. Das in diesem Beispiel verwendete JSON-Dokument verfügt über ein geschachteltes Array namens children, bei dem jedes untergeordnete Element ein geschachteltes Array von pets aufweist. Mit der folgenden Abfrage werden die untergeordneten Elemente aus den einzelnen Dokumenten analysiert, jedes Arrayobjekt als Zeile zurückgegeben und dann das pets-Array analysiert:

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;

Der erste OPENJSON-Befehl gibt ein Fragment des children-Arrays mithilfe der AS JSON-Klausel zurück. Dieses Arrayfragment wird der zweiten OPENJSON-Funktion bereitgestellt, die givenName zurückgibt, firstName jedes untergeordneten Elements, und das Arrays von pets. Das Array von pets wird der dritten OPENJSON-Funktion bereitgestellt, die das givenName-Element des Haustiers zurückgibt.

Die Ergebnisse dieser Abfrage sind in der folgenden Tabelle aufgeführt:

familyName childGivenName petName
Desai Jesse Goofy
Desai Jesse Shadow
Desai Lisa NULL

Das Stammdokument wird mit zwei children-Zeilen verknüpft, die beim ersten OPENJSON(children)-Aufruf von zwei Zeilen (oder Tupeln) zurückgegeben werden. Anschließend wird jede Zeile mit den neuen Zeilen verknüpft, die von OPENJSON(pets) mithilfe des OUTER APPLY-Operators generiert werden. Weil Jesse zwei Haustiere hat, ist (Desai, Jesse) mit zwei Zeilen verknüpft, die für Goofy und Shadow generiert werden. Lisa hat keine Haustiere, sodass für dieses Tupel keine Zeilen von OPENJSON(pets) zurückgegeben werden. Da jedoch OUTER APPLY verwendet wird, wird NULL in der Spalte zurückgegeben. Wenn CROSS APPLY anstelle von OUTER APPLY eingesetzt wird, wird Lisa nicht im Ergebnis zurückgegeben, da keine Zeilen für Haustiere vorhanden sind, die mit diesem Tupel verknüpft werden könnten.

Vergleichen von JSON_VALUE und JSON_QUERY

Der Hauptunterschied zwischen JSON_VALUE und JSON_QUERY ist, dass JSON_VALUE einen skalaren Wert zurückgibt, wogegen JSON_QUERY ein Objekt oder Array zurückgibt.

Betrachten Sie das folgende Beispiel eines JSON-Texts.

{
    "a": "[1,2]",
    "b": [1, 2],
    "c": "hi"
}

In diesem Beispiel-JSON-Text sind die Datenelemente „a“ und „c“ Zeichenfolgenwerte, während Datenelement „b“ ein Array ist. Die folgenden Ergebnisse werden von JSON_VALUE und JSON_QUERY zurückgegeben:

Pfad JSON_VALUE-Rückgaben JSON_QUERY-Rückgaben
$ NULL oder Fehler { "a": "[1,2]", "b": [1, 2], "c": "hi" }
$.a [1,2] NULL oder Fehler
$.b NULL oder Fehler [1,2]
$.b[0] 1 NULL oder Fehler
$.c hi NULL oder Fehler

Testen von JSON_VALUE und JSON_QUERY mit der AdventureWorks-Beispieldatenbank

Testen Sie die integrierten Funktionen, die in diesem Artikel beschrieben werden, indem Sie die folgenden Beispiele mit der AdventureWorks2022-Beispieldatenbank ausführen. Weitere Informationen zum Hinzufügen von JSON-Daten für Testzwecke durch Ausführen eines Skripts finden Sie unter Testen des in die JSON-Unterstützung integrierten Laufwerks.

Im folgenden Beispiel enthält die Info-Spalte in der Tabelle SalesOrder_json den JSON-Text.

Beispiel 1 – Gib sowohl Standardspalten als auch JSON-Daten zurück

Die folgende Abfrage gibt sowohl die relationalen Standardspalten sowie Werte aus einer JSON-Spalte zurück.

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;

Beispiel 2 – Aggregiere und filtere JSON-Werte

Die folgende Abfrage aggregiert Teilergebnisse nach Kundennamen (im JSON-Format gespeichert), und Status (gespeichert in einer normalen Spalte). Sie filtert dann die Ergebnisse nach Stadt (im JSON-Format gespeichert) und Bestelldatum (gespeichert in einer normalen Spalte).

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;

Aktualisieren von Eigenschaftswerten in JSON-Text mithilfe der JSON_MODIFY-Funktion

Die JSON_MODIFY-Funktion aktualisiert den Wert einer Eigenschaft in einer JSON-Zeichenfolge, und gibt die aktualisierte JSON-Zeichenfolge zurück.

Im folgenden Beispiel wird der Wert einer JSON-Eigenschaft in einer Variable aktualisiert, die JSON enthält.

SET @info = JSON_MODIFY(@jsonInfo, '$.info.address[0].town', 'London');

Weitere Informationen finden Sie unter JSON_MODIFY.