Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como inserir JSON em uma tabela no SQL Server


Se você tiver um documento JSON que precisa inserir em uma tabela em um banco de dados SQL Server, o OPENJSON() função pode ser exatamente o que você precisa.

OPENJSON() é uma função com valor de tabela que retorna JSON em formato tabular. Ou seja, ele converte seu JSON em um conjunto de resultados tabular composto por linhas e colunas. Portanto, permite inseri-lo em uma tabela.

Exemplo 1 – SELECIONAR EM


Neste exemplo, usamos SELECT * INTO para criar uma nova tabela e inserir o conteúdo do documento JSON nela.
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   
    );

Primeiro declarei uma variável e coloquei o JSON nela. Então eu usei um SELECT * INTO instrução para inserir seu conteúdo.

No entanto, você notará que usei uma cláusula WITH para definir um esquema. Basicamente, o que estou fazendo aqui é criar meus próprios nomes de coluna e seus respectivos tipos de dados e, em seguida, mapear cada chave JSON com uma coluna.

Na última linha, eu uso AS JSON para especificar que o conteúdo dessa coluna é um objeto ou matriz JSON.

Isso ficará claro quando eu selecionar o conteúdo da tabela.

Vamos fazer isso.
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" }     |
+---------+-----------+--------+------------------------------------------------------+

Assim, podemos ver que as três primeiras colunas contêm um valor diferente do documento JSON e a última coluna contém o JSON real para cada elemento da matriz.

Também podemos usar o sys.column visualização do catálogo do sistema verifique os nomes e tipos de coluna da tabela.
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           |
+----------+----------+--------------+

Mais uma vez, exatamente como especificamos.

Observe que sys.columns sempre retorna um max_length de -1 quando o tipo de dados da coluna for varchar(max) , nvarchar(max) , varbinary(max) , ou xml . Especificamos nvarchar(max) e assim o valor de -1 é exatamente como esperado.

Observe também que, quando você usa AS JSON (como fizemos na quarta coluna), você deve tornar essa coluna um nvarchar(max) .

Exemplo 2 – INSERIR EM


Aqui está o mesmo exemplo, exceto que desta vez inserimos o JSON em uma tabela que já existe.

Portanto, a primeira coisa que precisamos fazer é criar a tabela:
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

Agora que criamos isso, podemos prosseguir e inserir o conteúdo do nosso documento JSON nessa tabela.

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

A única diferença entre este e o exemplo anterior é que substituí o seguinte bit:
SELECT * INTO JsonCats1

Com isso:
INSERT INTO JsonCats2
SELECT * 

Assim, selecionar o conteúdo da tabela produzirá o mesmo resultado do exemplo 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" }     |
+---------+-----------+--------+------------------------------------------------------+

Exemplo 3 – Usando o esquema padrão


Nos exemplos anteriores eu defini meu próprio esquema. Ou seja, especifiquei os nomes das colunas para as tabelas e especifiquei os tipos de dados reais dessas colunas.

Se eu não tivesse feito isso, OPENJSON() teria usado o esquema padrão. O esquema padrão consiste em três colunas; chave , valor e tipo .

Aqui está um exemplo de como usar o esquema padrão ao inserir JSON em uma tabela.
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');

Portanto, a única diferença entre este e o primeiro exemplo é que eu removi todo o WITH cláusula. Essa é a parte que definiu o esquema nos dois exemplos anteriores.

Agora vamos verificar o conteúdo da tabela.
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 tabela contém as três colunas mencionadas. A coluna de valor contém cada elemento da matriz.

Exemplo 4 – Use chaves JSON como cabeçalhos de coluna


Este exemplo é um pouco um cruzamento entre os dois exemplos 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)
);

Ainda estamos definindo nosso próprio esquema, porque estamos usando o WITH cláusula. Mas você notará que não estou mapeando os nomes das colunas para nenhum caminho JSON. Isso ocorre porque estou usando os nomes reais das chaves JSON.

Quando você faz isso, OPENJSON() é inteligente o suficiente para corresponder os nomes das colunas às chaves JSON.

Vamos ver o que está na tabela.
SELECT * FROM JsonCats4;

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

Portanto, os dados foram inseridos na tabela, assim como nos dois primeiros exemplos, mas desta vez os nomes das colunas foram retirados do documento JSON.

Exemplo 5 – Especificar menos colunas


Você não precisa incluir todos os valores do documento JSON se não precisar de todos eles. Você pode especificar apenas aqueles que você precisa.

Você pode fazer isso especificando as colunas no 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   |
+------+-----------+

Outra maneira de fazer isso é remover a(s) coluna(s) relevante(s) do 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   |
+------+-----------+

Embora, provavelmente seja melhor fazer as duas coisas.
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   |
+------+-----------+

Exemplo 6 – Especificar menos linhas


Você também pode usar a sintaxe T-SQL normal para filtrar as linhas, para que apenas alguns registros sejam inseridos na tabela.
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 |
+------+-----------+

Neste caso eu usei um WHERE cláusula para inserir apenas as linhas nas quais estou interessado.

Importar JSON de um arquivo


Você pode usar OPENJSON() em conjunto com o OPENROWSET() função para importar um arquivo JSON para uma tabela.

Isso permite que você carregue os dados de um arquivo JSON em uma unidade local ou unidade de rede. Isso evita que você tenha que copiar e colar o conteúdo do documento em seu código SQL. Isso pode ser particularmente benéfico ao trabalhar com documentos JSON grandes.