Se hai un documento JSON che devi inserire in una tabella in un database di SQL Server, il OPENJSON()
la funzione potrebbe essere proprio ciò di cui hai bisogno.
OPENJSON()
è una funzione con valori di tabella che restituisce JSON in formato tabulare. Cioè, converte il tuo JSON in un set di risultati tabulare composto da righe e colonne. Pertanto, ti consente di inserirlo in una tabella.
Esempio 1 – SELEZIONA IN
In questo esempio, utilizziamo SELECT * INTO
per creare una nuova tabella e inserirvi il contenuto del documento JSON.
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
);
Per prima cosa ho dichiarato una variabile e ci ho inserito il JSON. Quindi ho usato un SELECT * INTO
dichiarazione per inserirne il contenuto.
Tuttavia, noterai che ho usato una clausola WITH per definire uno schema. Fondamentalmente quello che sto facendo qui è creare i miei nomi di colonna e i rispettivi tipi di dati, quindi mappare ciascuna chiave JSON con una colonna.
Nell'ultima riga, utilizzo AS JSON
per specificare che il contenuto di quella colonna è un oggetto o una matrice JSON.
Questo diventerà chiaro quando seleziono il contenuto della tabella.
Facciamolo.
SELECT * FROM JsonCats1;
Risultato:
+---------+-----------+--------+------------------------------------------------------+ | 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" } | +---------+-----------+--------+------------------------------------------------------+
Quindi possiamo vedere che le prime tre colonne contengono ciascuna un valore diverso dal documento JSON e l'ultima colonna contiene il JSON effettivo per ogni elemento dell'array.
Possiamo anche usare sys.column
la visualizzazione del catalogo di sistema controlla i nomi e i tipi delle colonne della tabella.
SELECT
name AS [Column],
TYPE_NAME(system_type_id) AS [Type],
max_length
FROM sys.columns
WHERE OBJECT_ID('JsonCats2') = object_id;
Risultato:
+----------+----------+--------------+ | Column | Type | max_length | |----------+----------+--------------| | Cat Id | int | 4 | | Cat Name | varchar | 60 | | Sex | varchar | 6 | | Cats | nvarchar | -1 | +----------+----------+--------------+
Ancora una volta, esattamente come l'avevamo specificato.
Nota che sys.columns
restituisce sempre un max_length
di -1
quando il tipo di dati della colonna è varchar(max) , nvarchar(max) , variabile(max) o xml . Abbiamo specificato nvarchar(max) e quindi il valore di -1
è esattamente come previsto.
Tieni inoltre presente che, quando utilizzi AS JSON
(come abbiamo fatto nella quarta colonna), devi rendere quella colonna un nvarchar(max) .
Esempio 2 – INSERIRE IN
Ecco lo stesso esempio, tranne che questa volta inseriamo il JSON in una tabella già esistente.
Pertanto, la prima cosa che dobbiamo fare è creare la tabella:
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
Ora che l'abbiamo creato, possiamo procedere e inserire il contenuto del nostro documento JSON in quella tabella.
In questo modo:
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
);
L'unica differenza tra questo e l'esempio precedente è che ho sostituito il seguente bit:
SELECT * INTO JsonCats1
Con questo:
INSERT INTO JsonCats2
SELECT *
Quindi, selezionando il contenuto della tabella si otterrà lo stesso risultato dell'esempio precedente.
SELECT * FROM JsonCats2;
Risultato:
+---------+-----------+--------+------------------------------------------------------+ | 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" } | +---------+-----------+--------+------------------------------------------------------+
Esempio 3:utilizzo dello schema predefinito
Negli esempi precedenti ho definito il mio schema. Cioè, ho specificato i nomi delle colonne per le tabelle e ho specificato i tipi di dati effettivi di quelle colonne.
Se non l'avessi fatto, OPENJSON()
avrebbe utilizzato lo schema predefinito. Lo schema predefinito è costituito da tre colonne; chiave , valore e digita .
Ecco un esempio di utilizzo dello schema predefinito quando si inserisce JSON in una tabella.
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');
Quindi l'unica differenza tra questo e il primo esempio è che ho rimosso l'intero WITH
clausola. Questo è il bit che ha definito lo schema nei due esempi precedenti.
Ora controlliamo il contenuto della tabella.
SELECT * FROM JsonCats3;
Risultato:
+-------+------------------------------------------------------+--------+ | 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 | +-------+------------------------------------------------------+--------+
Questa tabella contiene le tre colonne menzionate. La colonna del valore contiene ogni elemento dell'array.
Esempio 4:utilizzo di chiavi JSON come intestazioni di colonna
Questo esempio è un po' un incrocio tra i due esempi precedenti.
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)
);
Stiamo ancora definendo il nostro schema, perché stiamo usando il WITH
clausola. Ma noterai che non sto mappando i nomi delle colonne su nessun percorso JSON. Questo perché sto usando i nomi effettivi delle chiavi JSON.
Quando lo fai, OPENJSON()
è abbastanza intelligente da abbinare i nomi delle colonne alle chiavi JSON.
Vediamo cosa c'è nella tabella.
SELECT * FROM JsonCats4;
Risultato:
+------+-----------+--------+ | id | name | sex | |------+-----------+--------| | 1 | Fluffy | Female | | 2 | Long Tail | Female | | 3 | Scratch | Male | +------+-----------+--------+
Quindi i dati sono stati inseriti nella tabella, proprio come nei primi due esempi, ma questa volta i nomi delle colonne sono stati presi dal documento JSON.
Esempio 5:specificare meno colonne
Non è necessario includere tutti i valori del documento JSON se non sono necessari tutti. Puoi specificare solo quelli di cui hai bisogno.
Puoi farlo specificando le colonne in SELECT
elenco.
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;
Risultato:
+------+-----------+ | id | name | |------+-----------| | 1 | Fluffy | | 2 | Long Tail | | 3 | Scratch | +------+-----------+
Un altro modo per farlo è rimuovere la colonna o le colonne pertinenti da WITH
clausola.
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;
Risultato:
+------+-----------+ | id | name | |------+-----------| | 1 | Fluffy | | 2 | Long Tail | | 3 | Scratch | +------+-----------+
Anche se probabilmente è meglio fare entrambe le cose.
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;
Risultato:
+------+-----------+ | id | name | |------+-----------| | 1 | Fluffy | | 2 | Long Tail | | 3 | Scratch | +------+-----------+
Esempio 6:specificare meno righe
Puoi anche utilizzare la normale sintassi T-SQL per filtrare le righe, in modo che solo alcuni record vengano inseriti nella tabella.
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;
Risultato:
+------+-----------+ | id | name | |------+-----------| | 1 | Fluffy | | 2 | Long Tail | +------+-----------+
In questo caso ho usato un WHERE
clausola per inserire solo le righe che mi interessano.
Importa JSON da un file
Puoi usare OPENJSON()
insieme a OPENROWSET()
funzione per importare un file JSON in una tabella.
Ciò ti consente di caricare i dati da un file JSON su un'unità locale o un'unità di rete. Ciò ti evita di dover copiare e incollare il contenuto del documento nel tuo codice SQL. Ciò può essere particolarmente utile quando si lavora con documenti JSON di grandi dimensioni.