sql >> Base de Datos >  >> RDS >> Sqlserver

Cómo insertar JSON en una tabla en SQL Server

Si tiene un documento JSON que necesita insertar en una tabla en una base de datos de SQL Server, OPENJSON() función podría ser justo lo que necesita.

OPENJSON() es una función con valores de tabla que devuelve JSON en formato tabular. Es decir, convierte su JSON en un conjunto de resultados tabulares que consta de filas y columnas. Por lo tanto, le permite insertarlo en una tabla.

Ejemplo 1:SELECCIONAR EN

En este ejemplo, usamos SELECT * INTO para crear una nueva tabla e insertar en ella el contenido 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   
    );

Primero declaré una variable y puse el JSON en ella. Luego usé un SELECT * INTO instrucción para insertar su contenido.

Sin embargo, notará que usé una cláusula WITH para definir un esquema. Básicamente, lo que estoy haciendo aquí es crear mis propios nombres de columna y sus respectivos tipos de datos, luego mapear cada clave JSON con una columna.

En la última línea, uso AS JSON para especificar que el contenido de esa columna es un objeto o matriz JSON.

Esto quedará claro cuando seleccione el contenido de la tabla.

Hagámoslo.

SELECT * FROM JsonCats1;

Resultado:

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

Entonces podemos ver que las tres primeras columnas contienen cada una un valor diferente del documento JSON, y la última columna contiene el JSON real para cada elemento de la matriz.

También podemos usar la sys.column vista de catálogo del sistema verifique los nombres y tipos de columnas de la tabla.

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

Resultado:

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

Nuevamente, exactamente como lo especificamos.

Tenga en cuenta que sys.columns siempre devuelve un max_length de -1 cuando el tipo de datos de la columna es varchar(max) , nvarchar(máximo) , varbinario(máximo) o xml . Especificamos nvarchar(max) y entonces el valor de -1 es exactamente como se esperaba.

También tenga en cuenta que, cuando usa AS JSON (como hicimos en la cuarta columna), debe convertir esa columna en nvarchar(max) .

Ejemplo 2:INSERTAR EN

Aquí está el mismo ejemplo, excepto que esta vez insertamos el JSON en una tabla que ya existe.

Por lo tanto, lo primero que debemos hacer es crear la tabla:

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

Ahora que lo hemos creado, podemos continuar e insertar el contenido de nuestro documento JSON en esa tabla.

Así:

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 única diferencia entre este y el ejemplo anterior es que reemplacé el siguiente bit:

SELECT * INTO JsonCats1

Con esto:

INSERT INTO JsonCats2
SELECT * 

Entonces, seleccionar los contenidos de la tabla producirá el mismo resultado que el ejemplo anterior.

SELECT * FROM JsonCats2;

Resultado:

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

Ejemplo 3:uso del esquema predeterminado

En los ejemplos anteriores definí mi propio esquema. Es decir, especifiqué los nombres de las columnas de las tablas y especifiqué los tipos de datos reales de esas columnas.

Si no hubiera hecho eso, OPENJSON() habría utilizado el esquema predeterminado. El esquema predeterminado consta de tres columnas; clave , valor y tipo .

Este es un ejemplo del uso del esquema predeterminado al insertar JSON en una tabla.

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

Entonces, la única diferencia entre este y el primer ejemplo es que eliminé todo WITH cláusula. Esa es la parte que definió el esquema en los dos ejemplos anteriores.

Ahora revisemos el contenido de la tabla.

SELECT * FROM JsonCats3;

Resultado:

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

Esta tabla contiene las tres columnas mencionadas. La columna de valor contiene cada elemento de la matriz.

Ejemplo 4:use claves JSON como encabezados de columna

Este ejemplo es un poco un cruce entre los dos ejemplos anteriores.

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

Todavía estamos definiendo nuestro propio esquema, porque estamos usando WITH cláusula. Pero notará que no estoy asignando los nombres de las columnas a ninguna ruta JSON. Esto se debe a que estoy usando los nombres reales de las claves JSON.

Cuando haces eso, OPENJSON() es lo suficientemente inteligente como para hacer coincidir los nombres de sus columnas con las claves JSON.

Veamos qué hay en la tabla.

SELECT * FROM JsonCats4;

Resultado:

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

Entonces, los datos se insertaron en la tabla, al igual que en los dos primeros ejemplos, pero esta vez los nombres de las columnas se tomaron del documento JSON.

Ejemplo 5:especificar menos columnas

No necesita incluir todos los valores del documento JSON si no los necesita todos. Puede especificar solo los que necesite.

Puede hacer esto especificando las columnas en 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;

Resultado:

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

Otra forma de hacerlo es eliminar la/s columna/s relevante/s del WITH cláusula.

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;

Resultado:

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

Aunque, probablemente sea mejor hacer ambas cosas.

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;

Resultado:

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

Ejemplo 6:especificar menos filas

También puede usar la sintaxis normal de T-SQL para filtrar las filas, de modo que solo se inserten algunos registros en la tabla.

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;

Resultado:

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

En este caso usé un WHERE cláusula para insertar solo las filas que me interesan.

Importar JSON desde un archivo

Puede usar OPENJSON() junto con OPENROWSET() función para importar un archivo JSON en una tabla.

Esto le permite cargar los datos desde un archivo JSON en una unidad local o una unidad de red. Esto le evita tener que copiar y pegar el contenido del documento en su código SQL. Esto puede ser particularmente beneficioso cuando se trabaja con documentos JSON de gran tamaño.