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.