Turning JSON into a Table - sql

{
"ID":1,
"KEY1":"",
"ARRAYKEY1":[
{
"ARRAYKEY":""
"OBJECTKEY":{
"OBJ":""
}
}
]
}
Above is a JSON object I have stored in the database and I want to use OPENJSON to create a tabular format. I know I can do the whole OPENJSON WITH ( ) and manually create all the columns. I wanted to know if anyone has any idea of how to recursively or programatically create the table without having to identity each key for the table. I could end up having a couple dozen fields. I'm not worried about excluding any of the items. If I wanted to pull all the records back, where could I even begin with the new 2016 SQL Server?

Here is the official Documentation.
SET #json =
N'[
{ "id" : 2,"info": { "name": "John", "surname": "Smith" }, "age": 25 },
{ "id" : 5,"info": { "name": "Jane", "surname": "Smith" }, "dob": "2005-11-04T12:00:00" }
]'
SELECT *
FROM OPENJSON(#json)
WITH (id int 'strict $.id',
firstName nvarchar(50) '$.info.name', lastName nvarchar(50) '$.info.surname',
age int, dateOfBirth datetime2 '$.dob')

Related

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

SQL query OpenJson with deep nested arrays loop

I know there a lot of similar questions and answers here. I've read most of them but I'm unable to query nested arrays in a JSON structure. I'm lost in the CROSS APPLY's.
I'm actually querying a web API but for the sake of my question I've put it in a variable.
I'm trying to insert the ID (3519) and all the info of "worker_contracts" into a table.
declare #json nvarchar(max)
set #json = '
{
"data": [
{
"id": "3519",
"type": "affiliate_workers",
"attributes": {
"title": "mr",
"first_name": "John",
"last_name": "Doe",
"telephone": "+32 471 12 34 56",
"worker_contracts": [
{
"start_date": "2020-01-06",
"end_date": null,
"social_secretary_specific_data": {
"affiliate_id": 54,
"worker_details_id": 3378,
"start_date": "2020-01-06",
"end_date": null,
"affiliate_worker_id": 3519,
},
"work_hours_per_week": 25.0,
"comment": "",
"roster_week": [
{
"start_date": "2020-01-13",
"number_hours": 25
},
{
"start_date": "2020-01-06",
"number_hours": 25
}
],
"social_secretary_identifier": "123456"
},
{
"start_date": "2019-09-23",
"end_date": "2020-01-05",
"social_secretary_specific_data": {
"affiliate_id": 54,
"worker_details_id": 3378,
"start_date": "2019-09-23",
"end_date": "2020-01-05",
"affiliate_worker_id": 3519,
},
"work_hours_per_week": 21.0,
"comment": "",
"roster_week": [
{
"start_date": "2019-09-30",
"number_hours": 21
},
{
"start_date": "2019-09-23",
"number_hours": 21
}
],
"social_secretary_identifier": "123456"
}
],
"sodexo_reference": "56789",
"region": "Vlaanderen",
"identity_card_number": "A1122334455",
"can_work_with_animals": false
}
}
]
}
My SQL query only selects the start and end date values. I don't understand how I can add the other nested data.
insert into AffiliateWorkersContract_WRK
select WA.id, wc.*
from OpenJson((CAST(#json as nvarchar(max))),'$.data')
WITH (
id int,
worker_contracts nvarchar(max) as json
)
as WA
cross apply openjson (WA.worker_contracts)
with
(
start_date date '$.start_date',
end_date date '$.end_date',
) as WC
Thank you all for your help in advance.
Found the solution myself. I just had to keep going with the cross apply
insert into AffiliateWorkersContract_WRK
select WA.id, wawc.start_date, wawc.end_date, wawc.signing_date, wawc.contract_variability,
wawc.vehicle_type, wawc.addendum, wawc.work_hours_per_week,wawc.comment, wawc.social_secretary_identifier,
wssd.affiliate_id, wssd.worker_details_id, wssd.created_at, wssd.updated_at, wssd.affiliate_worker_id, wssd.comment, wssd.author_id,
wssd.parent_id, wssd.operating_headquarter_id, wssd.reference_period, wssd.varvar_ref_period_avg_minutes_per_week,
wssd.varvar_min_work_minutes_per_week, wssd.varvar_max_work_minutes_per_week
from OpenJson((CAST(#pootsy_AWWC_request as nvarchar(max))),'$.data')
WITH (
id int,
attributes nvarchar(max) as json
) as WA
cross apply openjson ((CAST(WA.attributes as nvarchar(max))))
WITH (
worker_contracts nvarchar(max) as json
) as WC
cross apply OpenJson ((CAST(WC.worker_contracts as nvarchar(max))))
WITH (
start_date date,
end_date date,
signing_date date,
contract_variability varchar(20),
vehicle_type varchar(20),
addendum varchar(10),
work_hours_per_week decimal(4,2),
comment nvarchar(max),
social_secretary_identifier int,
social_secretary_specific_data nvarchar(max) as json,
roster_week nvarchar(max) as json
) AS WAWC
cross apply OpenJson (WAWC.social_secretary_specific_data)
WITH (
affiliate_id int,
worker_details_id int,
created_at varchar(40),
updated_at varchar(40),
affiliate_worker_id int,
comment nvarchar(max),
author_id int,
parent_id int,
operating_headquarter_id int,
reference_period varchar(10),
varvar_ref_period_avg_minutes_per_week decimal(4,2),
varvar_min_work_minutes_per_week decimal(4,2),
varvar_max_work_minutes_per_week decimal(4,2)
) AS WSSD

Inserting into sql server tables (2016) from json

I have some json like this:
SET #json =N'[
{ "id" : 2,"name": "John", "surname": "Smith", "lastname":"", "age": 25 },
]'
I need to insert into table with a condition like IF LASTNAME IS EMPTY IN JSON THEN INSERT SURNAME INTO LASTNAME ELSE INSERT LASTNAME INTO LASTNAME
insert into mytable (id,firstname,lastname,age)
select id,name,case statement,age from openjson
WITH (id int 'strict $.id',name nvarchar(100) '$.name',case statement, age int '$.age');
Hi i think this query can respond :
DECLARE #json varchar(MAX)
SET #json =N'[
{ "id" : 2,"name": "John", "surname": "Smith", "lastname":"", "age": 25 },
{ "id" : 2,"name": "John", "surname": "Smith", "lastname":"TT", "age": 25 },
{ "id" : 2,"name": "John", "surname": "Smith", "lastname":"TEST", "age": 25 }
]'
select id,name,case when lastname = '' then surname else lastname end as lastnameup, age from openjson(#json)
WITH (id int 'strict $.id',name nvarchar(100) '$.name', surname nvarchar(100) '$.surname', lastname nvarchar(100) '$.lastname', age int '$.age');
EDIT for surname propose thanks to #Shnugo

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