Converting JSON file data values to SQL tables rows and columns - sql

I have the below code in JSON file :
{
"took": 196,
"timed_out": false,
"_shards": {
"total": 15,
"successful": 15,
"failed": 0
},
"hits": {
"total": 165,
"max_score": null,
"hits": [
{
"_index": "logstash-2018.11.22",
"_type": "nagios_core",
"_id": "AWc6C_EtHRYvW4hmI7sl",
"_score": null,
"_source": {
"message": "EXTERNAL COMMAND: ACKNOWLEDGE_SVC_PROBLEM;DE-Hoeheinoed-VOC1-SRV;ntp_timesync;2;0;0;Jaizel Jem Perdon;SN 307185410",
"#version": "1",
"#timestamp": "2018-11-22T06: 12: 00.307Z",
"host": "172.26.66.59",
"port": 44154,
"type": "nagios_core",
"epoch_timestamp": "1542867118",
"nagios_severity_label": "EXTERNAL COMMAND",
"nagios_external_command": "ACKNOWLEDGE_SVC_PROBLEM",
"nagios_host": "DE-Hoeheinoed-VOC1-SRV",
"nagios_service": "ntp_timesync",
"nagios_sticky": "2",
"nagios_notify": "0",
"nagios_persistent": "0",
"nagios_author": "Jaizel Jem Perdon",
"nagios_comment": "SN 307185410",
"utc_timestamp": "2018-11-22T06: 11: 58.000Z"
},
"sort": [
1542867120307
]
}
]
}
}
And i have the below code in SQL: However, I am getting null values in my result. As am new to JSON, am not able to find out the path of the JSON data values
Drop table if exists #Temp1
Declare #JSON nvarchar(max)
SELECT #JSON = BulkColumn
FROM OPENROWSET (BULK '\\DKRDSDFSROOT10\Data\_Temp\MEIPE\ITE1452552_02test.json', SINGLE_CLOB) as j
select #json as details
If (ISJSON(#json) = 1)
BEGIN
PRINT 'JOSN File is valid';
select * into #Temp1
from OPENJSON(#JSON, '$.hits')
WITH
(
[nagios_author] nvarchar(100) '$.hits.hits._source.nagios_author',
[nagios_comment] nvarchar(100) '$.hits.hits._source.nagios_comment'
)
END
ELse
Begin
PRINT 'JOSN File is invalid';
END
select * from #Temp1
Can someone please help me ?

You are using the second hits array in your json as an object, but its an array try to change your query as follows:
select * into #Temp1
from OPENJSON(#JSON, '$.hits')
WITH
(
[nagios_author] nvarchar(100) '$.hits.hits[0]._source.nagios_author',
[nagios_comment] nvarchar(100) '$.hits.hits[0]._source.nagios_comment'
)

I tried using below code and it worked
WITH
(
[nagios_author] nvarchar(100) '$.hits[0]._source.nagios_author',
[nagios_comment] nvarchar(100) '$.hits[0]._source.nagios_comment'
)

Related

insert json to sql table getting null

I have the following json , when i am trying to extract it to sql i get empty.
I need CusP.id, CusP.custldId ,cusfield.id, value
DECLARE #json NVARCHAR(MAX);
SELECT #json = '{
"includ": {
"cusP": {
"542310": {
"id": 542310,
"custldId": 155,
"cusfield": {
"id": 155,
"type": "custfi"
},
"projectId": 17435,
"project": {
"id": 17435,
"type": "projects"
},
"value": "META DATA",
"createdAt": "2022-01-16T05:11:20Z",
"createdBy": 222222
},
"21000": {
"id": 21000,
"custldId": 426,
"cusfield": {
"id": 426,
"type": "custfi"
},
"projectId": 786044,
"project": {
"id": 786044,
"type": "projects"
},
"value": "delta55",
"createdAt": "2022-01-17T10:03:07Z",
"createdBy": 333333
}
}
}
}'
This is what i am trying:
SELECT
D.cusPid,
d.[value],
c.cusfieldid,
cd.projectId
FROM OPENJSON(#json, '$.includ.cusP')
WITH (
cusPid NVARCHAR(max) '$.id',
[value] NVARCHAR(max) '$.value'
) D
CROSS APPLY OPENJSON(#json, '$.includ.cusP.custfi')
WITH (
cusfieldid VARCHAR(100) '$.id'
) C
CROSS APPLY OPENJSON(#json, '$.includ.cusP.project')
WITH (
projectId VARCHAR(100) '$.id'
) Cd;
that is the result i expect
cusPid
value
cusfieldid
projectId
542310
META DATA
155
17435
21000
delta55
426
786044
The problem is that the ID is also itself used as the key for a sub-property and OPENJSON does not allow variable paths (beyond arrays), so you need an extra level:
SELECT P.id AS cuspID, P.[value], P.cusfieldid, [projectId]
FROM OPENJSON(#json, '$.includ.cusP') J
CROSS APPLY OPENJSON(J.[value]) WITH (
id INT,
[value] NVARCHAR(MAX),
[projectId] INT,
cusfieldid INT '$.cusfield.id'
) P

Is there an UPDATE equivalent command to SELECT json data

Is there a way to update the data retrieved from the below select (in this case, change "MS220" to something else)? It's difficult enough to do select from JSON in some cases. I'm not sure how to update just a single element.
CREATE TABLE JData (
JsonData nvarchar(max)
)
INSERT INTO JData
(JsonData)
VALUES
('[
{
"Categories": [
{
"QuerySourceNames": [
"QAsset"
],
"Id": "eceae85a-ffc6-49f4-8f6a-78ce2b4b274e",
"Name": "emsdba"
}
],
"Id": "525b4f07-0f67-43ac-8070-a0e6c1ceb1b9",
"Name": "MS220"
}
]')
SELECT
ParamName
FROM [dbo].[JData] jsonData
CROSS APPLY OPENJSON (jsonData)
WITH
(
Categories nvarchar(max) AS json,
Id uniqueidentifier,
ParamName varchar(10) '$.Name'
);
Try JSON_MODIFY() with the path '$[0].Name'
UPDATE d
SET jsonData = JSON_MODIFY(jsonData, '$[0].Name', 'New Value')
FROM [dbo].[JData] d
Results:
[
{
"Categories": [
{
"QuerySourceNames": [
"QAsset"
],
"Id": "eceae85a-ffc6-49f4-8f6a-78ce2b4b274e",
"Name": "emsdba"
}
],
"Id": "525b4f07-0f67-43ac-8070-a0e6c1ceb1b9",
"Name": "New Value"
}
]
db<>fiddle here

Transform properties from JSON array into comma-separated string

I have a string column in an SQL-Server table on Azure which contains the following data:
{
"status": "success",
"data": [
{
"name": "Jane",
"type": 0
},
{
"name": "John",
"type": 0
}
]
}
How can it be transformed into a comma-separated string containing "Jane, John"?
Here how to achieve this via a snippet of some of my older code, you should be able to loop through the table and do this for each row. There may be a quicker way of doing it but this will work.
DECLARE #JSON NVARCHAR(200) = '{"status": "success", "data": [{"name": "Jane", "type": 0},{"name": "John", "type": 0}]}',
#result nvarchar(max) = ''
SELECT #result = #result + [value] + N', '
FROM (
SELECT DISTINCT data.value
FROM OPENJSON(#JSON, '$.data') as jsondata
CROSS APPLY OPENJSON(jsondata.value) as data
WHERE data.[key] = 'name') a
select #result = substring(#result, 1, (LEN(#result)-1))
select #result

Update JSON array using SQL Server

I have JSON like below:
{
"property": {
"commonProperty": "abc",
"Items": [
{
"ID": 1,
"Name": "a"
},
{
"ID": 2,
"Name": "a"
},
{
"ID": 3,
"Name": "b"
}
]
}
}
And what I want to achieve is to update Names to "c" where it's currently "a" using SQL Server (so I want to have result like below).
{
"property": {
"commonProperty": "abc",
"Items": [
{
"ID": 1,
"Name": "c"
},
{
"ID": 2,
"Name": "c"
},
{
"ID": 3,
"Name": "b"
}
]
}
}
As far as I know I cannot use JSON_MODIFY because it does not handles queries inside it's arguments and OPENJSON cannot be updated. Is there any method I can use?
EDIT note: added common property above Items.
You may try one of the following options:
Parse the '$.property.Items' JSON array as table using OPENJSON(), make an update, output the table's content as JSON using FOR JSON and modify the original JSON using JSON_MODIFY():
Build a dynamic statement. You can modify the input JSON using JSON_MODIFY() and the appropriate path. The path needs to be defined as a literal or from SQL Server 2017 as a variable, but using a wildcard is not possible (e.g. the statement SELECT #json = JSON_MODIFY(#json, '$.property.Items[0].Name', N'c') modifies the first item in the Items JSON array).
JSON:
DECLARE #json nvarchar(max) = N'{
"property":{
"commonProperty":"abc",
"Items":[
{
"ID":1,
"Name":"a"
},
{
"ID":2,
"Name":"a"
},
{
"ID":3,
"Name":"b"
}
]
}
}'
Statement (that parses the JSON as a table, modifies the table and outputs the table's content as JSON):
SELECT #json = JSON_MODIFY(
#json,
'$.property.Items',
(
SELECT
ID AS 'ID',
CASE WHEN Name = N'a' THEN N'c' ELSE Name END AS 'Name'
FROM OPENJSON(#json, '$.property.Items') WITH (ID int, Name nvarchar(50))
FOR JSON PATH
)
)
Dynamic statement:
DECLARE #stm nvarchar(max)
SET #stm = (
SELECT N'SET #json = JSON_MODIFY(#json, ''$.property.Items[' + [key] + N'].Name'', N''c''); '
FROM OPENJSON(#json, '$.property.Items')
WHERE JSON_VALUE([value], '$.Name') = N'a'
FOR XML PATH('')
)
PRINT #stm
EXEC sp_executesql #stm, N'#json nvarchar(max) OUTPUT', #json OUTPUT

SQL Server - How to transform JSON to Relational database

How can we use SQL to Convert a JSON statement into different tables?
For example we have JSON:
{"table1":
{"Name":"table1","Items":
[{"Id":1,"FirstName":"John",
"LastName":"Wen","Country":"UK",
"PostCode":1234,"Status":false,
"Date":"2018-09-18T08:30:32.91",}]},
"table2":
{"Name":"table2","Items":
[{"Id":1,"Name":"leo",
"StudentId":102,"CreatedDate":"2018-09-18","Location":"USA"}]}}
In the relational database, we will get two tables once the JSON is converted
For example, schema 'Table1':
Id FirstName LastName Country PostCode Status Date
1 John Wen UK 1234 false 2018-09-18T08:30:32.91
And the 'Table2' will look like:
Id Name StudentId CreateDate Location
1 Leo 102 2018-9-18 USA
Could anyone please give any advices on it.
You can do this using openjson and json_value functions. Try the following:
Declare #json nvarchar(max),#table1Items nvarchar(max), #table2Items nvarchar(max)
set #json='{
"table1": {
"Name": "table1",
"Items": [{
"Id": 1,
"FirstName": "John",
"LastName": "Wen",
"Country": "UK",
"PostCode": 1234,
"Status": false,
"Date": "2018-09-18T08:30:32.91"
}, {
"Id": 2,
"FirstName": "John1",
"LastName": "Wen1",
"Country": "UK1",
"PostCode": 12341,
"Status": true,
"Date": "2018-09-15T08:30:32.91"
}]
},
"table2": {
"Name": "table2",
"Items": [{
"Id": 1,
"Name": "leo",
"StudentId": 102,
"CreatedDate": "2018-09-18",
"Location": "USA"
}]
}
}'
set #table1Items=(select value from OpenJSON((select value from OpenJSON(#Json) where [key]='table1')) where [key]='Items')
set #table2Items=(select value from OpenJSON((select value from OpenJSON(#Json) where [key]='table2')) where [key]='Items')
--select for table 1
select JSON_VALUE(val,'$.Id') as ID,
JSON_VALUE(val,'$.FirstName') as FirstName,
JSON_VALUE(val,'$.LastName') as LastName,
JSON_VALUE(val,'$.Country') as Country,
JSON_VALUE(val,'$.PostCode') as PostCode,
JSON_VALUE(val,'$.Status') as Status,
JSON_VALUE(val,'$.Date') as Date
from
(
select value as val from openJSON(#table1Items)
) AS Table1JSON
--select for table 1
select JSON_VALUE(val,'$.Id') as ID,
JSON_VALUE(val,'$.Name') as FirstName,
JSON_VALUE(val,'$.StudentId') as LastName,
JSON_VALUE(val,'$.CreatedDate') as Country,
JSON_VALUE(val,'$.Location') as PostCode
from
(
select value as val from openJSON(#table2Items)
) AS Table2JSON
It is working exactly as you wanted. At the end, the two select statements return the tables as you mentioned. Just add them to your desired table using insert into select. I have also tried adding another object to table1 array and verified that it is working fine i.e. returning two rows for two objects. Hope this helps
If SQL Version 2016+ use OPENJSON AND with_clause:
https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql?view=sql-server-2017
DECLARE #JsonData NVARCHAR(MAX);
SET #JsonData = N'
{
"table1": {
"Name": "table1",
"Items": [
{
"Id": 1,
"FirstName": "John",
"LastName": "Wen",
"Country": "UK",
"PostCode": 1234,
"Status": false,
"Date": "2018-09-18T08:30:32.91"
},
{
"Id": 2,
"FirstName": "John1",
"LastName": "Wen1",
"Country": "UK1",
"PostCode": 12341,
"Status": true,
"Date": "2018-09-15T08:30:32.91"
}
]
},
"table2": {
"Name": "table2",
"Items": [
{
"Id": 1,
"Name": "leo",
"StudentId": 102,
"CreatedDate": "2018-09-18",
"Location": "USA"
}
]
}
}
';
--Table1
SELECT [a].[Id]
, [a].[FistName]
, [a].[Lastname]
, [a].[Country]
, [a].[PostCode]
, [a].[Status]
, [a].[Date]
FROM
OPENJSON(#JsonData, '$.table1.Items')
WITH (
[Id] INT '$.Id'
, [FistName] NVARCHAR(200) '$.FirstName'
, [Lastname] NVARCHAR(200) '$.LastName'
, [Country] NVARCHAR(200) '$.Country'
, [PostCode] NVARCHAR(200) '$.PostCode'
, [Status] NVARCHAR(200) '$.Status'
, [Date] DATETIME '$.Date'
) [a];
--Table2
SELECT [a].[Id]
, [a].[Name]
, [a].[StudentId]
, [a].[CreatedDate]
, [a].[Location]
FROM
OPENJSON(#JsonData, '$.table2.Items')
WITH (
[Id] INT '$.Id'
, [Name] NVARCHAR(200) '$.Name'
, [StudentId] INT '$.StudentId'
, [CreatedDate] DATETIME '$.CreatedDate'
, [Location] NVARCHAR(200) '$.Location'
) [a];
Try using OPENJSON function in SQL Server:
ReferenceLink_1
ReferenceLink_2