Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment insérer JSON dans une table dans SQL Server

Si vous avez un document JSON que vous devez insérer dans une table d'une base de données SQL Server, le OPENJSON() fonction pourrait être exactement ce dont vous avez besoin.

OPENJSON() est une fonction table qui renvoie JSON au format tabulaire. Autrement dit, il convertit votre JSON en un ensemble de résultats tabulaire composé de lignes et de colonnes. Il vous permet donc de l'insérer dans un tableau.

Exemple 1 - SÉLECTIONNER DANS

Dans cet exemple, nous utilisons SELECT * INTO pour créer un nouveau tableau et y insérer le contenu du document 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   
    );

J'ai d'abord déclaré une variable et mis le JSON dedans. Ensuite, j'ai utilisé un SELECT * INTO déclaration pour insérer son contenu.

Cependant, vous remarquerez que j'ai utilisé une clause WITH pour définir un schéma. En gros, ce que je fais ici, c'est créer mes propres noms de colonnes et leurs types de données respectifs, puis mapper chaque clé JSON avec une colonne.

Sur la dernière ligne, j'utilise AS JSON pour spécifier que le contenu de cette colonne est un objet ou un tableau JSON.

Cela deviendra clair lorsque je sélectionnerai le contenu du tableau.

Allons-y.

SELECT * FROM JsonCats1;

Résultat :

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

Nous pouvons donc voir que les trois premières colonnes contiennent chacune une valeur différente du document JSON, et la dernière colonne contient le JSON réel pour chaque élément du tableau.

Nous pouvons également utiliser le sys.column vue du catalogue système vérifier les noms et les types de colonne de la table.

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

Résultat :

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

Encore une fois, exactement comme nous l'avions spécifié.

Notez que sys.columns renvoie toujours un max_length de -1 lorsque le type de données de la colonne est varchar(max) , nvarchar(max) , varbinaire(max) , ou xml . Nous avons spécifié nvarchar(max) et donc la valeur de -1 est exactement comme prévu.

Notez également que, lorsque vous utilisez AS JSON (comme nous l'avons fait sur la quatrième colonne), vous devez faire de cette colonne un nvarchar(max) .

Exemple 2 - INSÉRER DANS

Voici le même exemple, sauf que cette fois nous insérons le JSON dans une table qui existe déjà.

Par conséquent, la première chose que nous devons faire est de créer la table :

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

Maintenant que nous avons créé cela, nous pouvons continuer et insérer le contenu de notre document JSON dans cette table.

Comme ceci :

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

La seule différence entre cet exemple et l'exemple précédent est que j'ai remplacé le bit suivant :

SELECT * INTO JsonCats1

Avec ceci :

INSERT INTO JsonCats2
SELECT * 

Ainsi, la sélection du contenu de la table produira le même résultat que l'exemple précédent.

SELECT * FROM JsonCats2;

Résultat :

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

Exemple 3 - Utilisation du schéma par défaut

Dans les exemples précédents, j'ai défini mon propre schéma. Autrement dit, j'ai spécifié les noms des colonnes pour les tables et j'ai spécifié les types de données réels de ces colonnes.

Si je ne l'avais pas fait, OPENJSON() aurait utilisé le schéma par défaut. Le schéma par défaut se compose de trois colonnes ; clé , valeur , et tapez .

Voici un exemple d'utilisation du schéma par défaut lors de l'insertion de JSON dans une table.

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

Donc, la seule différence entre ceci et le premier exemple, c'est que j'ai supprimé tout le WITH clause. C'est le bit qui a défini le schéma dans les deux exemples précédents.

Vérifions maintenant le contenu du tableau.

SELECT * FROM JsonCats3;

Résultat :

+-------+------------------------------------------------------+--------+
| 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      |
+-------+------------------------------------------------------+--------+

Ce tableau contient les trois colonnes mentionnées. La colonne de valeur contient chaque élément du tableau.

Exemple 4 – Utiliser des clés JSON comme en-têtes de colonne

Cet exemple est un peu un croisement entre les deux exemples précédents.

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

Nous sommes toujours en train de définir notre propre schéma, car nous utilisons le WITH clause. Mais vous remarquerez que je ne mappe pas les noms de colonne sur un chemin JSON. C'est parce que j'utilise les noms réels des clés JSON.

Lorsque vous faites cela, OPENJSON() est suffisamment intelligent pour faire correspondre vos noms de colonnes aux clés JSON.

Voyons ce qu'il y a dans le tableau.

SELECT * FROM JsonCats4;

Résultat :

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

Les données ont donc été insérées dans le tableau, comme dans les deux premiers exemples, mais cette fois les noms de colonnes ont été extraits du document JSON.

Exemple 5 - Spécifiez moins de colonnes

Vous n'avez pas besoin d'inclure toutes les valeurs du document JSON si vous n'en avez pas toutes besoin. Vous pouvez spécifier uniquement ceux dont vous avez besoin.

Vous pouvez le faire en spécifiant les colonnes dans le SELECT liste.

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;

Résultat :

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

Une autre façon de le faire est de supprimer la ou les colonnes pertinentes du WITH clause.

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;

Résultat :

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

Bien qu'il soit probablement préférable de faire les deux.

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;

Résultat :

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

Exemple 6 - Spécifiez moins de lignes

Vous pouvez également utiliser la syntaxe T-SQL normale pour filtrer les lignes, de sorte que seuls certains enregistrements soient insérés dans la table.

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;

Résultat :

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

Dans ce cas, j'ai utilisé un WHERE clause pour insérer uniquement les lignes qui m'intéressent.

Importer JSON à partir d'un fichier

Vous pouvez utiliser OPENJSON() en conjonction avec OPENROWSET() fonction pour importer un fichier JSON dans une table.

Cela vous permet de télécharger les données à partir d'un fichier JSON sur un lecteur local ou un lecteur réseau. Cela vous évite d'avoir à copier et coller le contenu du document dans votre code SQL. Cela peut être particulièrement avantageux lorsque vous travaillez avec des documents JSON volumineux.