Extract text from JSON in SQL Server - sql

I am trying to extract a specific value from a JSON column in SQL Server. Unfortunately I have read several posts on this topic but still cannot figure out how to translate their solutions to what I need. I am looking to extract "foo testing" but simply do not understand how to get at this with a nested JSON. Can someone please advise?
The structure of the JSON column is:
{
"values": [
{
"id": "x01",
"status": "STATUS1",
"subStatus": "SubStatus1",
"values": [
{
"key": "dropdown",
"value": "",
"optionType": null
}
]
},
...
{
"id": "x03",
"status": "STATUS3",
"subStatus": "SubStatus3",
"values": [
{
"key": "dropdown",
"value": "",
"optionType": null
},
{
"key": "textInput",
"value": null,
"optionType": null
},
{
"key": "checkbox1",
"value": true,
"optionType": null
},
{
"key": "textInput2",
"value": "foo testing",
"optionType": null
}
]
}
]
}

The statement depends on the structure of the parsed JSON, in your case you need to use two nested OPENJSON() calls and additinal APPLY operators. Note, that you need to use AS JSON in a "values" column definition to specify that the referenced property contains an inner JSON array and the type of that column must be nvarchar(max).
Test table:
DECLARE #json varchar(max) = '
{
"values": [
{
"id": "x01",
"status": "STATUS1",
"subStatus": "SubStatus1",
"values": [
{"key": "dropdown", "value": "", "optionType": null}
]
},
{
"id": "x03",
"status": "STATUS3",
"subStatus": "SubStatus3",
"values": [
{"key": "dropdown", "value": "", "optionType": null},
{"key": "textInput", "value": null, "optionType": null},
{"key": "checkbox1", "value": true, "optionType": null},
{"key": "textInput2", "value": "foo testing", "optionType": null}
]
}
]
}
'
SELECT JsonColumn
INTO JsonTable
FROM (VALUES (#json)) v (JsonColumn)
Statement:
SELECT j1.[id], j2.[key], j2.[value] -- or add all columns
FROM JsonTable t
CROSS APPLY OPENJSON(t.JsonColumn, '$.values') WITH (
[id] varchar(3) '$.id',
[status] varchar(30) '$.status',
[subStatus] varchar(30) '$.subStatus',
[values] nvarchar(max) '$.values' AS JSON
) j1
CROSS APPLY OPENJSON(j1.[values], '$') WITH (
[key] varchar(50) '$.key',
[value] varchar(50) '$.value',
[optionType] varchar(50) '$.optionType'
) j2
Result:
id key value
---------------------------
x01 dropdown
x03 dropdown
x03 textInput
x03 checkbox1 true
x03 textInput2 foo testing

you can use following query
;with summery as(
SELECT *
FROM OPENJSON((SELECT value FROM OPENJSON(#json)))
WITH (
id NVARCHAR(50) 'strict $.id',
status NVARCHAR(50) '$.status',
subStatus NVARCHAR(50) '$.subStatus',
[values] NVARCHAR(max) '$.values' AS JSON
)
)
select id,status,subStatus,[key],value,optionType from summery
CROSS APPLY OPENJSON(summery.[values])
WITH (
[key] NVARCHAR(50) '$.key',
[value] NVARCHAR(50) '$.value',
[optionType] NVARCHAR(50) '$.optionType'
);
demo in db<>fiddle

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

SQL Query to get the count of Json Array

I have the below Json object. How do I get the count of Object Array.
{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC"
},
{
"ID": 11,
"Name": "ABCD"
},
]
}]}
I tried the below query but seems JSON_Length was not available.
SELECT ModelName,
JSON_LENGTH(JsonData, '$.Model[0].Object')
FROM TabA
The expected output should be
ModelName COUNT
Test Model 2
If you have valid JSON (at the moment you have a trailing comma (,_ after one of your closing braces (})), then you could use OPENJSON and COUNT:
DECLARE #JSON nvarchar(MAX) = N'{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC"
},
{
"ID": 11,
"Name": "ABCD"
}
]
}]}';
SELECT M.ModelName,
COUNT(O.[key]) AS [Count]
FROM (VALUES(#JSON))V(J)
CROSS APPLY OPENJSON(V.J)
WITH(ModelName varchar(20) '$.Model[0].ModelName',
[Object] nvarchar(MAX) '$.Model[0].Object' AS JSON) M
CROSS APPLY OPENJSON(M.[Object]) O
GROUP BY M.ModelName;

Reading json array into rows in SQL Server

Given the sample json data below, how can I write a query to pull the array data all in one step? My goal is to have one row for each item in the ActionRecs array (4). My actual json is more complicated but I think this gives a good example of my goal.
declare #json2 nvarchar(max)
set #json2 = '{
"RequestId": "1",
"ActionRecs": [
{
"Type": "Submit",
"Employee": "Joe"
},
{
"Type": "Review",
"Employee": "Betty"
},
{
"Type": "Approve",
"Employee": "Sam"
},
{
"Type": "Approve",
"Employee": "Bill"
}
]
}'
SELECT x.*
, JSON_QUERY(#json2, '$.ActionRecs') as ActionArray
from OPENJSON(#json2)
with (Id varchar(5) '$.RequestId') as x
One possible approach is to use OPENJSON() with explicit schema and an additional CROSS APPLY operator:
DECLARE #json nvarchar(max)
SET #json = N'{
"RequestId": "1",
"ActionRecs": [
{"Type": "Submit", "Employee": "Joe"},
{"Type": "Review", "Employee": "Betty"},
{"Type": "Approve", "Employee": "Sam"},
{"Type": "Approve", "Employee": "Bill"}
]
}'
SELECT i.Id, a.[Type], a.[Employee]
FROM OPENJSON(#json) WITH (
Id varchar(5) '$.RequestId',
ActionRecs nvarchar(max) '$.ActionRecs' AS JSON
) AS i
CROSS APPLY OPENJSON(i.ActionRecs) WITH (
[Type] nvarchar(max) '$.Type',
[Employee] nvarchar(max) '$.Employee'
) a
Output:
Id Type Employee
1 Submit Joe
1 Review Betty
1 Approve Sam
1 Approve Bill

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