SQL- Merging json with a node name - sql

I have a table with json vaules in nvarchar columns
ID ConfigKey ConfigValue
1 employee {"name":"jhon","age":"23","salary":"5000"}
2 Dept {"name": "Marketing", "code":"12", "manager":"sam"}
3 manager {"managername":"abc", "dept":"AB"}
I need to get merged json for selected ConfiKey by adding ConfigKey value as node name for the ConfigValue and also merged json as below.
For example when i want to get for employee and manager. Output should be like
{
"employee": {
"name": "jhon",
"age": "23",
"salary": "5000"
},
"manager": {
"managername": "abc",
"dept": "AB"
}
}
When I want to get for only ConfigKey value employee output should be
{
"employee": {
"name": "jhon",
"age": "23",
"salary": "5000"
}
}
I tried using JSON_MODIFY but couldn't achieve this. How I can achieve this in SQL query.

You can do this with PIVOT and JSON_QUERY but the code will quickly get messy as you add more ConfigKey rows...
/*
* Setup example type, table and data...
*/
create type ConfigKeyTableType as table (
ConfigKey nvarchar(10)
);
create table dbo.Example (
ID int,
ConfigKey nvarchar(10),
ConfigValue nvarchar(max)
);
insert dbo.Example (ID, ConfigKey, ConfigValue) values
(1, N'employee', N'{"name":"jhon","age":"23","salary":"5000"}'),
(2, N'Dept', N'{"name": "Marketing", "code":"12", "manager":"sam"}'),
(3, N'manager', N'{"managername":"abc", "dept":"AB"}');
go
/*
* Stored procedure to return the JSON based on the supplied ConfigKey values...
*/
create procedure dbo.usp_GetConfigJSON (
#ConfigKeys ConfigKeyTableType readonly
)
as
begin
set nocount on;
select
json_query(dept) as [dept],
json_query(employee) as [employee],
json_query(manager) as [manager]
from (
select Ex.ConfigKey, Ex.ConfigValue
from dbo.Example Ex
join #ConfigKeys keys on keys.ConfigKey=Ex.ConfigKey
) src
pivot (max(ConfigValue) for ConfigKey in ([dept], [employee], [manager])) pvt
for json auto, without_array_wrapper;
end
go
To invoke it from SQL...
declare #ConfigKeys ConfigKeyTableType;
insert #ConfigKeys (ConfigKey) values
(N'employee'),
(N'manager');
exec dbo.usp_GetConfigJSON #ConfigKeys;
go
declare #ConfigKeys ConfigKeyTableType;
insert #ConfigKeys (ConfigKey) values
(N'employee');
exec dbo.usp_GetConfigJSON #ConfigKeys;
go
Which yields the results...
{
"employee": {
"name": "jhon",
"age": "23",
"salary": "5000"
},
"manager": {
"managername": "abc",
"dept": "AB"
}
}
...and...
{
"employee": {
"name": "jhon",
"age": "23",
"salary": "5000"
}
}

Related

Update json data in oracle sql

This is my json data in one of the oracle sql columns "jsoncol" in a table named "jsontable"
{
"Company": [
{
"Info": {
"Address": "123"
},
"Name": "ABC",
"Id": 999
},
{
"Info": {
"Address": "456"
},
"Name": "XYZ",
"Id": 888
}
]
}
I am looking for an UPDATE query to update all the value of "Name" with a new value based on a particular "Id" value.
Thanks in advance
From Oracle 19, you can use JSON_MERGEPATCH:
UPDATE jsontable j
SET jsoncol = JSON_MERGEPATCH(
jsoncol,
(
SELECT JSON_OBJECT(
KEY 'Company'
VALUE JSON_ARRAYAGG(
CASE id
WHEN 999
THEN JSON_MERGEPATCH(
json,
'{"Name":"DEF"}'
)
ELSE json
END
FORMAT JSON
RETURNING CLOB
)
FORMAT JSON
RETURNING CLOB
)
FROM jsontable jt
CROSS APPLY JSON_TABLE(
jt.jsoncol,
'$.Company[*]'
COLUMNS(
json VARCHAR2(4000) FORMAT JSON PATH '$',
id NUMBER PATH '$.Id'
)
)
WHERE jt.ROWID = j.ROWID
)
)
Which, for the sample data:
CREATE TABLE jsontable (
jsoncol CLOB CHECK (jsoncol IS JSON)
);
INSERT INTO jsontable (jsoncol)
VALUES ('{
"Company": [
{
"Info": {
"Address": "123"
},
"Name": "ABC",
"Id": 999
},
{
"Info": {
"Address": "456"
},
"Name": "XYZ",
"Id": 888
}
]
}');
Then after the UPDATE, the table contains:
JSONCOL
{"Company":[{"Info":{"Address":"123"},"Name":"DEF","Id":999},{"Info":{"Address":"456"},"Name":"XYZ","Id":888}]}
db<>fiddle here
You can use REPLACE() within JSON_TABLE() function in order to update the value of the Name(from ABC to DEF) for a specific Id value(999) such as
UPDATE jsontable jt0
SET jsoncol = ( SELECT REPLACE(jsoncol,jt.name,'DEF')
FROM jsontable j,
JSON_TABLE(jsoncol,
'$' COLUMNS(NESTED PATH '$.Company[*]'
COLUMNS(
name VARCHAR2 PATH '$.Name',
id INT PATH '$.Id'
)
)
) jt
WHERE jt.id = 999
AND j.id = jt0.id )
for the DB version prior to 19 provided that the identity values(id) of the table and of the JSON values are unique throughout the table and each individual JSON value, respectively.
Demo

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

How to retrieve specific JSON value from a column containing a JSON array

I have this JSON array in a SQL Server table:
[
{
"FieldName": "DateCreated",
"FieldValue": "10/22/2020"
},
{
"FieldName": "IsMember",
"FieldValue": "false"
},
{
"FieldName": "EntityId",
"FieldValue": "ABC123"
}
]
I want to fetch only the FieldValue of the EntityId object, so the output should be only ABC123.
I have this query
SELECT JSON_VALUE(JsonColumnData, '$[2].FieldValue') AS EntityId
FROM MyTable
This returns the EntityId value, but the thing is that I have no guarantee that the EntityId will always be in the same position of the JSON array.
Is it possible to have the select return the EntityId regardless of its position in the JSON array?
You can use OPENJSON() to query the data and just filter the row(s) that contain EntityId...
create table dbo.MyTable (
JsonColumnData nvarchar(max)
);
insert dbo.MyTable (JsonColumnData) values (N'[
{
"FieldName": "DateCreated",
"FieldValue": "10/22/2020"
},
{
"FieldName": "IsMember",
"FieldValue": "false"
},
{
"FieldName": "EntityId",
"FieldValue": "ABC123"
}
]');
select FieldValue as EntityId
from dbo.MyTable
cross apply openjson(JsonColumnData) with (
FieldName nvarchar(11),
FieldValue nvarchar(11)
)
where FieldName = N'EntityId';
Which yields...
EntityId
---------
ABC123

JSON from SQL query with child level

I have a simple query in my database:
SELECT id, name FROM users FOR JSON AUTO, ROOT('users')
This returns the following JSON:
{
"users": [
{"id": "1", "name": "John"}
{"id": "2", "name": "Mike"}
]
}
I want to have the return with the following format:
{
"users": {
"list": [
{"id": "1", "name": "John"}
{"id": "2", "name": "Mike"}
]
}
}
Can I do this on SQL level by simply changing the query?
You may try with this:
Table:
CREATE TABLE users (
id varchar(1),
[name] varchar(50)
)
INSERT INTO users
(id, [name])
VALUES
('1', 'John'),
('2', 'Mike')
Statement:
SELECT users = (SELECT id, name FROM users FOR JSON AUTO, ROOT('list'))
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
Result:
{"users":{"list":[{"id":"1","name":"John"},{"id":"2","name":"Mike"}]}}

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