sql >> Databasteknik >  >> RDS >> Sqlserver

Hur man infogar JSON i en tabell i SQL Server

Om du har ett JSON-dokument som du behöver infoga i en tabell i en SQL Server-databas, visas OPENJSON() funktion kan vara precis vad du behöver.

OPENJSON() är en tabellvärderad funktion som returnerar JSON i tabellformat. Det vill säga, den konverterar din JSON till en tabellformad resultatuppsättning som består av rader och kolumner. Därför kan du infoga den i en tabell.

Exempel 1 – VÄLJ IN

I det här exemplet använder vi SELECT * INTO för att skapa en ny tabell och infoga innehållet i JSON-dokumentet i den.

DECLARE @json NVARCHAR(4000) = N'{ 
    "pets" : {
            "cats" : [
            { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
            { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
            { "id" : 3, "name" : "Scratch", "sex" : "Male" }
        ],
            "dogs" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT * INTO JsonCats1
FROM OPENJSON(@json, '$.pets.cats')
WITH  (
        CatId     int             '$.id',  
        CatName   varchar(60)     '$.name', 
        Sex       varchar(6)      '$.sex', 
        Cats      nvarchar(max)   '$' AS JSON   
    );

Jag deklarerade först en variabel och satte in JSON i den. Sedan använde jag en SELECT * INTO uttalande för att infoga dess innehåll.

Du kommer dock att märka att jag använde en WITH-sats för att definiera ett schema. Det jag gör här är att skapa mina egna kolumnnamn och deras respektive datatyper och sedan mappa varje JSON-nyckel med en kolumn.

På sista raden använder jag AS JSON för att ange att innehållet i den kolumnen är ett JSON-objekt eller en array.

Detta blir tydligt när jag väljer innehållet i tabellen.

Låt oss göra det.

SELECT * FROM JsonCats1;

Resultat:

+---------+-----------+--------+------------------------------------------------------+
| CatId   | CatName   | Sex    | Cats                                                 |
|---------+-----------+--------+------------------------------------------------------|
| 1       | Fluffy    | Female | { "id" : 1, "name" : "Fluffy", "sex" : "Female" }    |
| 2       | Long Tail | Female | { "id" : 2, "name" : "Long Tail", "sex" : "Female" } |
| 3       | Scratch   | Male   | { "id" : 3, "name" : "Scratch", "sex" : "Male" }     |
+---------+-----------+--------+------------------------------------------------------+

Så vi kan se att de tre första kolumnerna var och en innehåller ett annat värde än JSON-dokumentet, och den sista kolumnen innehåller den faktiska JSON för varje matriselement.

Vi kan också använda sys.column systemkatalogvy kontrollera tabellens kolumnnamn och typer.

SELECT
    name AS [Column],
    TYPE_NAME(system_type_id) AS [Type],
    max_length
FROM sys.columns 
WHERE OBJECT_ID('JsonCats2') = object_id;

Resultat:

+----------+----------+--------------+
| Column   | Type     | max_length   |
|----------+----------+--------------|
| Cat Id   | int      | 4            |
| Cat Name | varchar  | 60           |
| Sex      | varchar  | 6            |
| Cats     | nvarchar | -1           |
+----------+----------+--------------+

Återigen, exakt hur vi hade specificerat det.

Observera att sys.columns returnerar alltid en max_length av -1 när kolumndatatypen är varchar(max) , nvarchar(max) , varbinary(max) eller xml . Vi angav nvarchar(max) och så värdet på -1 är precis som förväntat.

Observera också att när du använder AS JSON (som vi gjorde i den fjärde kolumnen), måste du göra den kolumnen till en nvarchar(max) .

Exempel 2 – INSERT INTO

Här är samma exempel, förutom att vi den här gången infogar JSON i en tabell som redan finns.

Därför är det första vi behöver göra att skapa tabellen:

CREATE TABLE [dbo].[JsonCats2](
	[CatId] [int] NULL,
	[CatName] [varchar](60) NULL,
	[Sex] [varchar](6) NULL,
	[Cats] [nvarchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

Nu när vi har skapat det kan vi gå vidare och infoga innehållet i vårt JSON-dokument i den tabellen.

Så här:

DECLARE @json NVARCHAR(4000) = N'{ 
    "pets" : {
            "cats" : [
            { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
            { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
            { "id" : 3, "name" : "Scratch", "sex" : "Male" }
        ],
            "dogs" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

INSERT INTO JsonCats2
SELECT * 
FROM OPENJSON(@json, '$.pets.cats')
WITH  (
        CatId     int             '$.id',  
        CatName   varchar(60)     '$.name', 
        Sex       varchar(6)      '$.sex', 
        Cats      nvarchar(max)   '$' AS JSON   
    );

Den enda skillnaden mellan detta och föregående exempel är att jag ersatte följande bit:

SELECT * INTO JsonCats1

Med detta:

INSERT INTO JsonCats2
SELECT * 

Så att välja innehållet i tabellen ger samma resultat som föregående exempel.

SELECT * FROM JsonCats2;

Resultat:

+---------+-----------+--------+------------------------------------------------------+
| CatId   | CatName   | Sex    | Cats                                                 |
|---------+-----------+--------+------------------------------------------------------|
| 1       | Fluffy    | Female | { "id" : 1, "name" : "Fluffy", "sex" : "Female" }    |
| 2       | Long Tail | Female | { "id" : 2, "name" : "Long Tail", "sex" : "Female" } |
| 3       | Scratch   | Male   | { "id" : 3, "name" : "Scratch", "sex" : "Male" }     |
+---------+-----------+--------+------------------------------------------------------+

Exempel 3 – Använda standardschemat

I de tidigare exemplen definierade jag mitt eget schema. Det vill säga, jag angav namnen på kolumnerna för tabellerna och jag angav de faktiska datatyperna för dessa kolumner.

Om jag inte hade gjort det, OPENJSON() skulle ha använt standardschemat. Standardschemat består av tre kolumner; nyckel , värde och skriv .

Här är ett exempel på hur du använder standardschemat när du infogar JSON i en tabell.

DECLARE @json NVARCHAR(4000) = N'{ 
    "pets" : {
            "cats" : [
            { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
            { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
            { "id" : 3, "name" : "Scratch", "sex" : "Male" }
        ],
            "dogs" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT * INTO JsonCats3
FROM OPENJSON(@json, '$.pets.cats');

Så den enda skillnaden mellan detta och det första exemplet är att jag tog bort hela WITH klausul. Det är den bit som definierade schemat i de två föregående exemplen.

Låt oss nu kontrollera innehållet i tabellen.

SELECT * FROM JsonCats3;

Resultat:

+-------+------------------------------------------------------+--------+
| key   | value                                                | type   |
|-------+------------------------------------------------------+--------|
| 0     | { "id" : 1, "name" : "Fluffy", "sex" : "Female" }    | 5      |
| 1     | { "id" : 2, "name" : "Long Tail", "sex" : "Female" } | 5      |
| 2     | { "id" : 3, "name" : "Scratch", "sex" : "Male" }     | 5      |
+-------+------------------------------------------------------+--------+

Denna tabell innehåller de tre kolumnerna som nämnts. Värdekolumnen innehåller varje matriselement.

Exempel 4 – Använd JSON-nycklar som kolumnrubriker

Det här exemplet är lite av en korsning mellan de två föregående exemplen.

DECLARE @json NVARCHAR(4000) = N'{ 
    "pets" : {
            "cats" : [
            { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
            { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
            { "id" : 3, "name" : "Scratch", "sex" : "Male" }
        ],
            "dogs" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT * INTO JsonCats4
FROM OPENJSON(@json, '$.pets.cats')
WITH (
    id int,
    name varchar(60),
    sex varchar(6)
);

Vi definierar fortfarande vårt eget schema eftersom vi använder WITH klausul. Men du kommer att märka att jag inte mappar kolumnnamnen till någon JSON-sökväg. Detta beror på att jag använder de faktiska namnen på JSON-nycklarna.

När du gör det, OPENJSON() är smart nog att matcha dina kolumnnamn med JSON-nycklarna.

Låt oss se vad som står i tabellen.

SELECT * FROM JsonCats4;

Resultat:

+------+-----------+--------+
| id   | name      | sex    |
|------+-----------+--------|
| 1    | Fluffy    | Female |
| 2    | Long Tail | Female |
| 3    | Scratch   | Male   |
+------+-----------+--------+

Så data har infogats i tabellen, precis som i de två första exemplen, men den här gången har kolumnnamnen tagits från JSON-dokumentet.

Exempel 5 – Ange färre kolumner

Du behöver inte inkludera alla värden från JSON-dokumentet om du inte behöver alla. Du kan ange bara de som du behöver.

Du kan göra detta genom att ange kolumnerna i SELECT lista.

DECLARE @json NVARCHAR(4000) = N'{ 
    "pets" : {
            "cats" : [
            { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
            { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
            { "id" : 3, "name" : "Scratch", "sex" : "Male" }
        ],
            "dogs" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT 
    id, 
    name 
INTO JsonCats5a
FROM OPENJSON(@json, '$.pets.cats')
WITH (
    id int,
    name varchar(60),
    sex varchar(6)
);

SELECT * FROM JsonCats5a;

Resultat:

+------+-----------+
| id   | name      |
|------+-----------|
| 1    | Fluffy    |
| 2    | Long Tail |
| 3    | Scratch   |
+------+-----------+

Ett annat sätt att göra det är att ta bort relevanta kolumner från WITH klausul.

DECLARE @json NVARCHAR(4000) = N'{ 
    "pets" : {
            "cats" : [
            { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
            { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
            { "id" : 3, "name" : "Scratch", "sex" : "Male" }
        ],
            "dogs" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT * INTO JsonCats5b
FROM OPENJSON(@json, '$.pets.cats')
WITH (
    id int,
    name varchar(60)
);

SELECT * FROM JsonCats5b;

Resultat:

+------+-----------+
| id   | name      |
|------+-----------|
| 1    | Fluffy    |
| 2    | Long Tail |
| 3    | Scratch   |
+------+-----------+

Även om det förmodligen är bättre att göra båda.

DECLARE @json NVARCHAR(4000) = N'{ 
    "pets" : {
            "cats" : [
            { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
            { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
            { "id" : 3, "name" : "Scratch", "sex" : "Male" }
        ],
            "dogs" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT 
    id,
    name
INTO JsonCats5c
FROM OPENJSON(@json, '$.pets.cats')
WITH (
    id int,
    name varchar(60)
);

SELECT * FROM JsonCats5c;

Resultat:

+------+-----------+
| id   | name      |
|------+-----------|
| 1    | Fluffy    |
| 2    | Long Tail |
| 3    | Scratch   |
+------+-----------+

Exempel 6 – Ange färre rader

Du kan också använda normal T-SQL-syntax för att filtrera raderna, så att endast vissa poster infogas i tabellen.

DECLARE @json NVARCHAR(4000) = N'{ 
    "pets" : {
            "cats" : [
            { "id" : 1, "name" : "Fluffy", "sex" : "Female" },
            { "id" : 2, "name" : "Long Tail", "sex" : "Female" },
            { "id" : 3, "name" : "Scratch", "sex" : "Male" }
        ],
            "dogs" : [
            { "name" : "Fetch", "sex" : "Male" },
            { "name" : "Fluffy", "sex" : "Male" },
            { "name" : "Wag", "sex" : "Female" }
        ]
    }
}';

SELECT 
    id,
    name
INTO JsonCats6
FROM OPENJSON(@json, '$.pets.cats')
WITH (
    id int,
    name varchar(60)
)
WHERE id IN (1,2);

SELECT * FROM JsonCats6;

Resultat:

+------+-----------+
| id   | name      |
|------+-----------|
| 1    | Fluffy    |
| 2    | Long Tail |
+------+-----------+

I det här fallet använde jag en WHERE sats för att infoga bara de rader som jag är intresserad av.

Importera JSON från en fil

Du kan använda OPENJSON() i kombination med OPENROWSET() funktion för att importera en JSON-fil till en tabell.

Detta gör att du kan ladda upp data från en JSON-fil på en lokal enhet eller nätverksenhet. Detta sparar dig från att behöva kopiera och klistra in dokumentets innehåll i din SQL-kod. Detta kan vara särskilt fördelaktigt när du arbetar med stora JSON-dokument.


  1. Hur man får datumet från en sträng i Oracle

  2. Förstå Always ON Availability Group mellan Linux-baserade SQL Server-instanser. Del 1

  3. Optimera sökfrågan med OFFSET på stort bord

  4. XML-prestandatips