Neste artigo
ToggleOlá pessoal,
Tudo bem com vocês ?
Neste post vou demonstrar como utilizar o suporte nativo do banco de dados SQL Server ao JSON, padrão de documento muito utilizado em integrações e Webservices atualmente. Esse recurso está disponível a partir da versão 2016 do SQL Server e tem como objetivo, permitir a exportação de dados do banco para uma string no formato JSON e a leitura e manipulação de dados no formato JSON.
Caso você esteja utilizando uma versão anterior ao SQL Server 2016, ou seja, sem suporte nativo a JSON, mas mesmo assim precisa trabalhar com strings JSON, leia o meu post Lendo strings JSON, importando para o banco e exportando para XML no SQL Server e saiba como fazer isso.
Caso você precise importar/exportar as strings JSON de/para arquivos texto fisicamente, confira esses dois posts:
- SQL Server – Como importar arquivos de texto para o banco (OLE Automation, CLR, BCP, BULK INSERT, OPENROWSET)
- SQL Server – Como exportar dados do banco para arquivo texto (CLR, OLE, BCP)
Exportando dados do banco para uma string JSON
Visualizar conteúdoSua sintaxe é muito parecida com a do XML, então se você já sabe manipular XML pelo SQL Server, você já estará bem familiarizado com esse novo recurso da versão 2016. Caso você não conheça, veja mais acessando o post SQL Server – Como ler, importar e exportar dados de arquivos XML.
Exemplo 1
Neste primeiro exemplo, vou utilizar o modo padrão do JSON, que é o auto. Ele simplesmente vai gerar o JSON de acordo com os dados informados, sem fazer nenhuma modificação em sua estrutura.
1 2 3 |
SELECT name, state_desc, recovery_model_desc FROM sys.databases FOR JSON AUTO |
JSON gerado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
[ { "name": "master", "state_desc": "ONLINE", "recovery_model_desc": "SIMPLE" }, { "name": "tempdb", "state_desc": "ONLINE", "recovery_model_desc": "SIMPLE" }, { "name": "model", "state_desc": "ONLINE", "recovery_model_desc": "FULL" }, { "name": "msdb", "state_desc": "ONLINE", "recovery_model_desc": "SIMPLE" }, { "name": "CLR", "state_desc": "ONLINE", "recovery_model_desc": "SIMPLE" }, { "name": "dirceuresende", "state_desc": "ONLINE", "recovery_model_desc": "SIMPLE" } ] |
Exemplo 2
Agora neste exemplo, vou utilizar o parâmetro ROOT para definir um elemento raiz para a minha string JSON e também vou mudar o títulos dos campos.
1 2 3 |
SELECT name AS [Database], state_desc AS [Situacao], recovery_model_desc AS [Recovery] FROM sys.databases FOR JSON PATH, ROOT('databases') |
JSON gerado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
{ "databases": [ { "Database": "master", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database": "tempdb", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database": "model", "Situacao": "ONLINE", "Recovery": "FULL" }, { "Database": "msdb", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database": "CLR", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database": "dirceuresende", "Situacao": "ONLINE", "Recovery": "SIMPLE" } ] } |
Exemplo 3
Neste exemplo, vou demonstrar 2 opções para se usar com o JSON. O parâmetro INCLUDE_NULL_VALUES serve para incluir as colunas com valor NULL na string JSON gerada (por padrão, colunas com valor NULL não são geradas). O parâmetro WITHOUT_ARRAY_WRAPPER serve para remover os caracteres “[” e “]” da string JSON gerada.
1 2 3 4 5 6 7 |
SELECT [name] AS [database.name], state_desc AS [database.state], create_date AS [database.create_date], NULL AS [database.valor_nulo] FROM sys.databases FOR JSON PATH, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER |
Resultado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
{ "database": { "name": "master", "state": "ONLINE", "create_date": "2003-04-08T09:13:36.390", "valor_nulo": null } }, { "database": { "name": "tempdb", "state": "ONLINE", "create_date": "2017-02-12T04:26:38.907", "valor_nulo": null } }, { "database": { "name": "model", "state": "ONLINE", "create_date": "2003-04-08T09:13:36.390", "valor_nulo": null } }, { "database": { "name": "msdb", "state": "ONLINE", "create_date": "2016-04-30T00:46:38.773", "valor_nulo": null } }, { "database": { "name": "CLR", "state": "ONLINE", "create_date": "2017-01-24T19:54:11.247", "valor_nulo": null } }, { "database": { "name": "dirceuresende", "state": "ONLINE", "create_date": "2017-02-08T13:35:32.370", "valor_nulo": null } } |
Exemplo 4
Neste exemplo, vou demonstrar como exportar os dados de uma tabela e armazenar a string JSON gerada em uma variável.
1 2 3 4 5 6 7 8 9 10 |
DECLARE @stringJson VARCHAR(MAX) = ( SELECT TOP 2 [name] AS [database.name], state_desc AS [database.state], recovery_model_desc AS [database.options.recovery] FROM sys.databases FOR JSON AUTO ) PRINT @stringJson |
Exemplo 5
Neste última exemplo, vou demonstrar como controlar completamente a estrutura da sua string JSON utilizando o parâmetro PATH.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
SELECT TOP 2 [name] AS [database.name], state_desc AS [database.state], recovery_model_desc AS [database.options.recovery], [compatibility_level] AS [database.options.compatibility_level], page_verify_option_desc AS [database.options.page_verify], collation_name AS [database.options.collation], create_date AS [database.create_date], is_read_only AS [database.parameters.read_only], is_auto_shrink_on AS [database.parameters.auto_shrink], is_auto_create_stats_on AS [database.parameters.auto_create_stats], is_read_committed_snapshot_on AS [database.parameters.sessions.read_commited_snapshot], is_ansi_null_default_on AS [database.parameters.sessions.ansi_nulls], is_ansi_warnings_on AS [database.parameters.sessions.ansi_warnings], is_arithabort_on AS [database.parameters.sessions.arithabort], user_access_desc AS [database.user_access] FROM sys.databases FOR JSON PATH, ROOT('databases') |
JSON gerado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
{ "databases": [ { "database": { "name": "master", "state": "ONLINE", "options": { "recovery": "SIMPLE", "compatibility_level": 130, "page_verify": "CHECKSUM", "collation": "Latin1_General_CI_AI" }, "create_date": "2003-04-08T09:13:36.390", "parameters": { "read_only": false, "auto_shrink": false, "auto_create_stats": true, "sessions": { "read_commited_snapshot": false, "ansi_nulls": false, "ansi_warnings": false, "arithabort": false } }, "user_access": "MULTI_USER" } }, { "database": { "name": "tempdb", "state": "ONLINE", "options": { "recovery": "SIMPLE", "compatibility_level": 130, "page_verify": "CHECKSUM", "collation": "Latin1_General_CI_AI" }, "create_date": "2017-02-12T04:26:38.907", "parameters": { "read_only": false, "auto_shrink": false, "auto_create_stats": true, "sessions": { "read_commited_snapshot": false, "ansi_nulls": false, "ansi_warnings": false, "arithabort": false } }, "user_access": "MULTI_USER" } } ] } |
Manipulando dados em strings JSON com JSON_VALUE
Visualizar conteúdoExemplo 1
Neste primeiro exemplo, vou demonstrar como extrair informações rapidamente utilizando a função JSON_VALUE.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
DECLARE @stringJson VARCHAR(MAX) = ' { "info":{ "type":1, "address":{ "town":"Bristol", "county":"Avon", "country":"England" }, "tags":["Sport", "Water polo"] }, "type":"Basic" }' SELECT JSON_VALUE(@stringJson, '$.info.type') AS [info_type], JSON_VALUE(@stringJson, '$.info.address.town') AS [town], JSON_VALUE(@stringJson, '$.info.address.county') AS [county], JSON_VALUE(@stringJson, '$.info.address.country') AS [country], -- para retornar o array, utilize JSON_QUERY JSON_VALUE(@stringJson, '$.info.tags') AS [tags], -- retornando os dados do array JSON_VALUE(@stringJson, '$.info.tags[0]') AS [tags1], JSON_VALUE(@stringJson, '$.info.tags[1]') AS [tags2], JSON_VALUE(@stringJson, '$.info.tags[2]') AS [tags3], -- não existe = NULL JSON_VALUE(@stringJson, '$.type') AS [type] |
Exemplo 2
Neste exemplo, vou demonstrar como ler dados de strings JSON que possuem dados multivalorados (arrays) e a leitura será feita utilizando índices de arrays.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
DECLARE @stringJson VARCHAR(MAX) = ' { "databases": [ { "Database Name": "master", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "tempdb", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "model", "Situacao": "ONLINE", "Recovery": "FULL" }, { "Database Name": "msdb", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "CLR", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "dirceuresende", "Situacao": "ONLINE", "Recovery": "SIMPLE" } ] }' SELECT JSON_VALUE(@stringJson, '$.databases[0]."Database Name"'), JSON_VALUE(@stringJson, '$.databases[0].Situacao'), JSON_VALUE(@stringJson, '$.databases[1]."Database Name"'), JSON_VALUE(@stringJson, '$.databases[1].Situacao'), JSON_VALUE(@stringJson, '$.databases[2]."Database Name"'), JSON_VALUE(@stringJson, '$.databases[2].Situacao'), JSON_VALUE(@stringJson, '$.databases[5]."Database Name"'), JSON_VALUE(@stringJson, '$.databases[5].Situacao') |
Exemplo 3
Neste exemplo, vou demonstrar como utilizar o JSON_VALUE utilizando uma string embutida no próprio comando.
1 2 3 |
SELECT JSON_VALUE('{"Primeiro Nome":"Dirceu", "Ultimo Nome": "Resende"}', '$."Primeiro Nome"'), JSON_VALUE('{"Primeiro Nome":"Dirceu", "Ultimo Nome": "Resende"}', '$."Ultimo Nome"') |
Exemplo 4
Por fim, neste exemplo vou demonstrar como utilizar a função JSON_VALUE como coluna computada, onde insiro uma string JSON na tabela, e os dados são calculados automaticamente pra mim.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
IF (OBJECT_ID('tempdb..#Teste') IS NOT NULL) DROP TABLE #Teste CREATE TABLE #Teste ( Id INT IDENTITY(1 ,1), stringJson VARCHAR(MAX), Nome AS JSON_VALUE(stringJson, '$."Primeiro Nome"'), Ultimo_Nome AS JSON_VALUE(stringJson, '$."Ultimo Nome"'), ) INSERT #Teste (stringJson) VALUES('{"Primeiro Nome":"Dirceu", "Ultimo Nome": "Resende"}') SELECT * FROM #Teste |
Manipulando dados em strings JSON com JSON_QUERY
Visualizar conteúdoExemplo 1
Neste primeiro exemplo, vou demonstrar algumas utilizações básicas da função JSON_QUERY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
DECLARE @stringJson VARCHAR(MAX) = ' { "info": { "type": 1, "address": { "town": "Bristol", "county": "Avon", "country": "England" }, "tags": ["Sport", "Water polo"] }, "type": "Basic" } ' SELECT -- Retorna o objeto JSON completo JSON_QUERY(@stringJson, '$') AS JSON_Completo SELECT -- Retorna o objeto JSON "info" JSON_QUERY(@stringJson, '$.info') AS [Info] SELECT -- Retorna o objeto JSON "address" JSON_QUERY(@stringJson, '$.info.address') AS [Address] SELECT -- Retorna NULL, pois JSON_QUERY só funciona com objetos -- Para retornar valores escalares, use a JSON_VALUE JSON_QUERY(@stringJson, '$.info.type') AS [Type] SELECT -- Retorna o array de valores da propriedade "tags JSON_QUERY(@stringJson, '$.info.tags') AS [Tags] |
Exemplo 2
Neste exemplo, vou demonstrar como retornar arrays utilizando índices-N a partir de uma string JSON.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
DECLARE @stringJson VARCHAR(MAX) = ' { "databases": [ { "Database Name": "master", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "tempdb", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "model", "Situacao": "ONLINE", "Recovery": "FULL" }, { "Database Name": "msdb", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "CLR", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "dirceuresende", "Situacao": "ONLINE", "Recovery": "SIMPLE" } ] }' SELECT JSON_QUERY(@stringJson, '$.databases[0]') SELECT JSON_QUERY(@stringJson, '$.databases[1]') SELECT JSON_QUERY(@stringJson, '$.databases[2]') |
Exemplo 3
Neste exemplo, vou fazer algumas comparações entre o JSON_QUERY e JSON_VALUE, para demonstrar a diferença das 2 funções.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
DECLARE @stringJson VARCHAR(MAX) = ' { "databases": [ { "database": { "name": "master", "teste": ["Teste 1", "Teste 2", "Teste 3"], "state": "ONLINE", "options": { "recovery": "SIMPLE", "compatibility_level": 130, "page_verify": "CHECKSUM", "collation": "Latin1_General_CI_AI" }, "create_date": "2003-04-08T09:13:36.390", "parameters": { "read_only": false, "auto_shrink": false, "auto_create_stats": true, "sessions": { "read_commited_snapshot": false, "ansi_nulls": false, "ansi_warnings": false, "arithabort": false } }, "user_access": "MULTI_USER" } }, { "database": { "name": "tempdb", "teste": ["Teste 1", "Teste 2", "Teste 3"], "state": "ONLINE", "options": { "recovery": "SIMPLE", "compatibility_level": 130, "page_verify": "CHECKSUM", "collation": "Latin1_General_CI_AI" }, "create_date": "2017-02-12T04:26:38.907", "parameters": { "read_only": false, "auto_shrink": false, "auto_create_stats": true, "sessions": { "read_commited_snapshot": false, "ansi_nulls": false, "ansi_warnings": false, "arithabort": false } }, "user_access": "MULTI_USER" } } ] }' -- Quando usar o JSON_QUERY para retornar objetos SELECT JSON_QUERY(@stringJson, '$') AS [JSON_Query], JSON_VALUE(@stringJson, '$') AS [JSON_Value] SELECT JSON_QUERY(@stringJson, '$.databases[0]') AS [JSON_Query], JSON_VALUE(@stringJson, '$.databases[0]') AS [JSON_Value] SELECT JSON_QUERY(@stringJson, '$.databases[0].database') AS [JSON_Query], JSON_VALUE(@stringJson, '$.databases[0].database') AS [JSON_Value] SELECT JSON_QUERY(@stringJson, '$.databases[0].database.teste') AS [JSON_Query], JSON_VALUE(@stringJson, '$.databases[0].database.teste') AS [JSON_Value] SELECT JSON_QUERY(@stringJson, '$.databases[0].database.options') AS [JSON_Query], JSON_VALUE(@stringJson, '$.databases[0].database.options') AS [JSON_Value] -- Quando usar o JSON_VALUE para retornar valores SELECT JSON_QUERY(@stringJson, '$.databases[0].database.teste[0]') AS [JSON_Query], JSON_VALUE(@stringJson, '$.databases[0].database.teste[0]') AS [JSON_Value], JSON_QUERY(@stringJson, '$.databases[0].database.teste[1]') AS [JSON_Query], JSON_VALUE(@stringJson, '$.databases[0].database.teste[1]') AS [JSON_Value] SELECT JSON_QUERY(@stringJson, '$.databases[0].database.name') AS [JSON_Query], JSON_VALUE(@stringJson, '$.databases[0].database.name') AS [JSON_Value] SELECT JSON_QUERY(@stringJson, '$.databases[0].database.options.recovery') AS [JSON_Query], JSON_VALUE(@stringJson, '$.databases[0].database.options.recovery') AS [JSON_Value] |
Validando strings JSON com a função ISJSON
Visualizar conteúdoVou demonstrar alguns exemplos para vocês entenderem facilmente como se utilizar essa função.
Exemplo 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
DECLARE @stringJson VARCHAR(MAX) = ' { "info":{ "type":1, "address":{ "town":"Bristol", "county":"Avon", "country":"England" }, "tags":["Sport", "Water polo"] }, "type":"Basic" }' SELECT ISJSON(@stringJson) |
Resultado:
1 (JSON válido)
Exemplo 2
Neste exemplo, vou usar exatamente o mesmo JSON do exemplo anterior, mas vou remover um bracket “]” da string JSON para que ele não seja mais válido.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
-- Removi o caractere "]" da linha 12 DECLARE @stringJson VARCHAR(MAX) = ' { "info":{ "type":1, "address":{ "town":"Bristol", "county":"Avon", "country":"England" }, "tags":["Sport", "Water polo" }, "type":"Basic" }' SELECT ISJSON(@stringJson) |
Resultado:
0 (JSON inválido)
Exemplo 3
Por fim, vou demonstrar alguns exemplos rápidos de validação de JSON.
1 2 3 4 5 6 |
SELECT ISJSON('Teste') AS Invalido1, ISJSON('') AS Invalido2, ISJSON(NULL) AS Retorna_Null, ISJSON('{"Primeiro Nome":"Dirceu", "Ultimo Nome": "Resende"}') AS Valido1, ISJSON('"Primeiro Nome":"Dirceu", "Ultimo Nome": "Resende"') AS Invalido3 |
Importando JSON para tabela com OPENJSON
Visualizar conteúdoExemplo 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
DECLARE @stringJson VARCHAR(MAX) = ' { "databases": [ { "Database Name": "master", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "tempdb", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "model", "Situacao": "ONLINE", "Recovery": "FULL" }, { "Database Name": "msdb", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "CLR", "Situacao": "ONLINE", "Recovery": "SIMPLE" }, { "Database Name": "dirceuresende", "Situacao": "ONLINE", "Recovery": "SIMPLE" } ] }' SELECT * FROM OPENJSON(@stringJson, '$.databases') WITH ( Ds_Database NVARCHAR(100) '$."Database Name"', Ds_Situacao NVARCHAR(40) '$.Situacao', Ds_Recovery NVARCHAR(20) '$.Recovery' ) AS JsonImportado |
Exemplo 2
Neste exemplo, vou demonstrar como importar outro JSON, desta vez sem elemento raiz e vou converter a data para DATETIME.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
DECLARE @stringJson VARCHAR(MAX) = ' [ {"Pedido": 1, "Dt_Pedido": "18/02/2017", "Cd_Cliente": 25, "Qtde_Itens": 5, "Cd_Produto": 5, "Vl_Unitario": 154.54}, {"Pedido": 4, "Dt_Pedido": "14/02/2017", "Cd_Cliente": 7, "Qtde_Itens": 6, "Cd_Produto": 4, "Vl_Unitario": 59.99}, {"Pedido": 6, "Dt_Pedido": "12/02/2017", "Cd_Cliente": 9, "Qtde_Itens": 8, "Cd_Produto": 2, "Vl_Unitario": 150}, {"Pedido": 8, "Dt_Pedido": "12/02/2017", "Cd_Cliente": 5, "Qtde_Itens": 1, "Cd_Produto": 8, "Vl_Unitario": 287.00} ]' SELECT JsonImportado.Nr_Pedido , CONVERT(DATETIME, JsonImportado.Dt_Pedido, 103) AS Dt_Pedido, JsonImportado.Cd_Cliente , JsonImportado.Qtde_Itens , JsonImportado.Cd_Produto , JsonImportado.Vl_Unitario FROM OPENJSON(@stringJson) WITH ( Nr_Pedido INT '$.Pedido', Dt_Pedido NVARCHAR(10) '$.Dt_Pedido', Cd_Cliente INT '$.Cd_Cliente', Qtde_Itens INT '$.Qtde_Itens', Cd_Produto INT '$.Cd_Produto', Vl_Unitario FLOAT '$.Vl_Unitario' ) AS JsonImportado |
Exemplo 3
Neste exemplo, vou demonstrar como importar dados de uma string JSON multinível para tabela.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
DECLARE @stringJson VARCHAR(MAX) = ' { "databases": [ { "database": { "name": "master", "state": "ONLINE", "options": { "recovery": "SIMPLE", "compatibility_level": 130, "page_verify": "CHECKSUM", "collation": "Latin1_General_CI_AI" }, "create_date": "2003-04-08T09:13:36.390", "parameters": { "read_only": false, "auto_shrink": false, "auto_create_stats": true, "sessions": { "read_commited_snapshot": false, "ansi_nulls": false, "ansi_warnings": false, "arithabort": false } }, "user_access": "MULTI_USER" } }, { "database": { "name": "tempdb", "state": "ONLINE", "options": { "recovery": "SIMPLE", "compatibility_level": 130, "page_verify": "CHECKSUM", "collation": "Latin1_General_CI_AI" }, "create_date": "2017-02-12T04:26:38.907", "parameters": { "read_only": false, "auto_shrink": false, "auto_create_stats": true, "sessions": { "read_commited_snapshot": false, "ansi_nulls": false, "ansi_warnings": false, "arithabort": false } }, "user_access": "MULTI_USER" } } ] }' SELECT * FROM OPENJSON(@stringJson, '$.databases') WITH ( [Database_Name] NVARCHAR(100) '$.database.name', [Database_State] NVARCHAR(100) '$.database.state', [Recovery] NVARCHAR(40) '$.database.options.recovery', [Compatibility_Level] INT '$.database.options.compatibility_level', [Page_Verify] NVARCHAR(20) '$.database.options.page_verify', [Collation] NVARCHAR(50) '$.database.options.collation', -- Informação booleada em variável BIT [Read_Only] BIT '$.database.parameters.read_only', [Read_Commited_Snapshot] BIT '$.database.parameters.sessions.read_commited_snapshot', -- Informação booleada em variável NVARCHAR [Ansi_Nulls] NVARCHAR(50) '$.database.parameters.sessions.ansi_nulls', [Ansi_Warnings] NVARCHAR(50) '$.database.parameters.sessions.ansi_warnings', [Arithabort] NVARCHAR(50) '$.database.parameters.sessions.arithabort', [User_Acess] NVARCHAR(40) '$.database.user_access' ) AS JsonImportado |
Exemplo 4
Neste exemplo, vou demonstrar como importar dados de uma string JSON multinível, retornando apenas a listagem, para tabela. Nesse cenário, terei que utilizar CROSS APPLY entre os nós do JSON para percorrê-lo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
DECLARE @json NVARCHAR(MAX) = ' [ { "sendSmsMultiResponse":{ "testToken": "ok", "sendSmsResponseList":[ { "statusCode":"00", "statusDescription":"Ok", "detailCode":"000", "detailDescription":"Message Sent" }, { "statusCode":"01", "statusDescription":"Ok", "detailCode":"000", "detailDescription":"Message Sent" }, { "statusCode":"02", "statusDescription":"Ok", "detailCode":"000", "detailDescription":"Message Delivered" }, { "statusCode":"03", "statusDescription":"Error", "detailCode":"000", "detailDescription":"Failure Sending Message" }, { "statusCode":"04", "statusDescription":"Ok", "detailCode":"000", "detailDescription":"Message Sent" } ] } } ]' SELECT lista.testToken, items.* FROM OPENJSON(@json) WITH ( sendSmsMultiResponse NVARCHAR(MAX) AS JSON ) AS retorno CROSS APPLY OPENJSON(retorno.sendSmsMultiResponse) WITH ( testToken NVARCHAR(100), sendSmsResponseList NVARCHAR(MAX) AS JSON ) AS lista CROSS APPLY OPENJSON(lista.sendSmsResponseList) WITH ( statusCode NVARCHAR(10), statusDescription NVARCHAR(50), detailCode NVARCHAR(10), detailDescription NVARCHAR(50) ) AS items |
Exemplo 5
Neste último exemplo, vou demonstrar novamente como importar dados de uma string JSON multinível, retornando apenas a listagem, para tabela. Nesse cenário, terei que utilizar CROSS APPLY entre os nós do JSON para percorrê-lo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
DECLARE @json NVARCHAR(MAX) = ' [ { "structures":[ { "IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F", "IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47", "Name":"Test Structure", "BaseStructure":"Base Structure", "DatabaseSchema":"dbo", "properties":[ { "IdProperty":"618DC40B-4D04-4BF8-B1E6-12E13DDE86F4", "IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F", "Name":"Test Property 2", "DataType":1, "Precision":2, "Scale":0, "IsNullable":false, "ObjectName":"Test Object", "DefaultType":0, "DefaultValue":"T" }, { "IdProperty":"FFF433EC-0BB5-41CD-8A71-B5F09B97C5FC", "IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F", "Name":"Test Property 1", "DataType":2, "Precision":4, "Scale":0, "IsNullable":true, "ObjectName":"Test Object 2", "DefaultType":1, "DefaultValue":"F" } ] } ] } ]' SELECT Structures.IdStructure, Structures.Name, Structures.BaseStructure, Structures.DatabaseSchema, Properties.IdProperty, Properties.NamePreoperty, Properties.DataType, Properties.Precision, Properties.Scale, Properties.IsNullable, Properties.ObjectName, Properties.DefaultType, Properties.DefaultValue FROM OPENJSON(@json) WITH ( structures NVARCHAR(MAX) AS JSON ) AS Projects CROSS APPLY OPENJSON(Projects.structures) WITH ( IdStructure UNIQUEIDENTIFIER, [Name] NVARCHAR(100), BaseStructure NVARCHAR(100), DatabaseSchema sysname, properties NVARCHAR(MAX) AS JSON ) AS Structures CROSS APPLY OPENJSON(Structures.properties) WITH ( IdProperty UNIQUEIDENTIFIER, NamePreoperty NVARCHAR(100) '$.Name', DataType INT, [Precision] INT, [Scale] INT, IsNullable BIT, ObjectName NVARCHAR(100), DefaultType INT, DefaultValue NVARCHAR(100) ) AS Properties |
Modificando strings JSON com JSON_MODIFY
Visualizar conteúdoExemplo de uso
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
DECLARE @info NVARCHAR(MAX) = '{"nome":"Mike","habilidades":["C#","SQL"],"idade":29}' PRINT '-- JSON Original' PRINT @info PRINT '' -- Altera o nome de "Mike" para "Dirceu" SET @info=JSON_MODIFY(@info,'$.nome','Dirceu') PRINT '-- Altera o nome de "Mike" para "Dirceu"' PRINT @info PRINT '' -- Insere uma nova propriedade chamada "sobrenome" com o valor "Resende" SET @info=JSON_MODIFY(@info,'$.sobrenome','Resende') PRINT '-- Insere uma nova propriedade chamada "sobrenome" com o valor "Resende"' PRINT @info PRINT '' -- Adiciona um novo valor no array "habilidades" SET @info=JSON_MODIFY(@info,'append $.habilidades','Azure') PRINT '-- Adiciona um novo valor no array "habilidades"' PRINT @info PRINT '' -- Tenta redefiner os valores do array "habilidades" SET @info=JSON_MODIFY(@info,'$.habilidades', '["C++","T-SQL","PHP", "CSS"]') PRINT '-- Tenta redefiner os valores do array "habilidades", mas tem problemas com os caracteres não-escapados' PRINT @info PRINT '' -- Redefine os valores do array "habilidades" SET @info=JSON_MODIFY(@info,'$.habilidades', JSON_QUERY('["C++","T-SQL","PHP", "CSS"]')) PRINT '-- Redefine os valores do array "habilidades" utilizando JSON_QUERY para escapar os caracteres corretamente' PRINT @info PRINT '' -- Renomeando a propriedade "nome" para "Primeiro Nome" (Precisa excluir e criar uma nova) SET @info = JSON_MODIFY(@info, '$."Primeiro Nome"', JSON_VALUE(@info, '$.nome')) SET @info = JSON_MODIFY(@info, '$.nome', NULL) PRINT '-- Renomeando a propriedade "nome" para "Primeiro Nome"' PRINT @info PRINT '' -- Remove a propriedade ""Primeiro Nome"" SET @info=JSON_MODIFY(@info,'$."Primeiro Nome"',NULL) PRINT '-- Remove a propriedade "primeiroNome"' PRINT @info PRINT '' -- Incrementa o valor da propriedade "Idade" de 29 para 30 SET @info = JSON_MODIFY(@info, '$.idade', CAST(JSON_VALUE(@info, '$.idade') AS INT) + 1) PRINT '-- Incrementa o valor da propriedade "Idade" de 29 para 30' PRINT @info PRINT '' -- Realiza mais de uma atualização no mesmo comando SET @info = JSON_MODIFY(JSON_MODIFY(JSON_MODIFY(@info, '$.idade', 28), '$."Primeiro Nome"', 'Resende'), '$.sobrenome', 'Dirceu') PRINT '-- Realiza mais de uma atualização no mesmo comando' PRINT @info PRINT '' |
É isso aí, pessoal!
Espero que tenham gostado desse post.
Até a próxima.
Bacana Dirceu, parabéns!
Obrigado pelo feedback, Ronaldo. Qualquer dúvida, é só falar.
Não ficou claro para mim como se armazena um JSON dentro de uma tabela. Existe um tipo de dados para JSON nativamente? Você tem operadores para este tipo de dados para utilizar numa cláusula WHERE? É possível indexar um JSON?
Telles,
Bom dia.
O JSON é armazenado como string (VARCHAR ou NVARCHAR), diferente do XML, que possui um tipo de dado específico para ele. Os operadores para trabalhar com JSON em um WHERE são os mesmos do SELECT, como ISJON, JSON_VALUE, etc.. Assim como uma string qualquer, você pode indexar as strings JSON normalmente.
Vou editar o post depois para adicionar esses exemplos. 🙂
Entendi, é como o PostgreSQL fazia na primeira implementação do JSON. Mas o que passamos a fazer depois disso é indexar rótulos internos do JSON, EX: recovery_model_desc = ‘COMPLEX’;
O SQL Server faz isso?