I want to convert actual_arrival and actual_departure to human readable date and then see everything as a simple table. For now I'm getting an error:
Conversion failed when converting date and/or time from character string
How to do that?
Declare #json varchar(MAX) = '
{"stops":
{
"type": "stop",
"name": "stops",
"company_id": "xxx",
"actual_arrival": "20210910130000-0500",
"actual_departure": "20210910140000-0500"}
}';
SELECT *
FROM OPENJSON ( #json, '$.stops' )
WITH (
Type Varchar(50) '$.type',
Name Varchar(50) '$.name',
CompID Varchar(100) '$.company_id' ,
AcArrvl DATETIME '$.actual_arrival' ,
AcDprtr DATETIME '$.actual_departure') as j1
I think the problem is the formatting of the datetimeoffset. Also you are probably looking to convert into datetimeoffset to preserv time offset? This works for me (not that pretty but you have to reformat the string to yyyy-MM-dd hh:mm:ss-hh:mm):
Declare #json varchar(MAX) = '
{"stops":
{
"type": "stop",
"name": "stops",
"company_id": "xxx",
"actual_arrival": "20210910130000-0500",
"actual_departure": "20210910140000-0500"}
}';
SELECT
Type,
Name,
CompID,
CONVERT(DATETIMEOFFSET,
STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(AcArrvl,
18,0,':'),
13,0,':'),
11,0,':'),
9,0,' '),
7,0,'-'),
5,0,'-')
) AcArrvl,
CONVERT(DATETIMEOFFSET,
STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(AcDprtr,
18,0,':'),
13,0,':'),
11,0,':'),
9,0,' '),
7,0,'-'),
5,0,'-')
) AcDprtr
FROM OPENJSON ( #json, '$.stops' )
WITH (
Type Varchar(50) '$.type',
Name Varchar(50) '$.name',
CompID Varchar(100) '$.company_id' ,
AcArrvl VARCHAR(100) '$.actual_arrival' ,
AcDprtr VARCHAR(100) '$.actual_departure') as j1
Related
I have to insert some data from JSON to SQL database so I use below code:
sqlQuery1 = "DECLARE #json varchar(max)='" + inputData + "';";
sqlQuery2 = "INSERT INTO [Test].[dbo].[Work] " +
"SELECT [Id], [Created], [Assignee] " +
"FROM OPENJSON(#json) "+
"WITH ([Id] int '$.id',"+
"[Created] datetimeoffset(4) '$.fields.created',"+
"[Assignee] varchar(200) '$.fields.assignee.name')";
System.out.println(sqlQuery2); stmt.addBatch(sqlQuery1);stmt.addBatch(sqlQuery2); break;
$fields.created date has format eg: "2021-03-04T07:11:40.000+0000"
I tried using different way but not able to insert above format date into SQL.
Kindly help me with this code to insert created date to db.
Thank you in advance
SQL Server expects the time zone portion of your datetimeoffset string to include the colon character, i.e.: +00:00 instead of just +0000.
You will need to extract it from JSON as a varchar/nvarchar column first so that you can insert the : character before converting it to a datetimeoffset like so:
declare #json nvarchar(max) = N'{
"expand": "operations,versionedRepresentations,editmeta,changelog,renderedFields",
"id": "180",
"fields": {
"created": "2021-03-04T07:11:40.000+0000",
"assignee": {
"name": "pallavi"
}
}
}';
select *
from openjson(#json) with (
[Id] int '$.id',
[Created] varchar(29) '$.fields.created',
[Assignee] varchar(200) '$.fields.assignee.name'
) shredded
outer apply (
select [CreatedDatetimeoffset] = convert(datetimeoffset, stuff(Created, 27, 0, ':'))
) converted;
My SQL server
Query
DECLARE #json NVarChar(max)='{
"LoginName" : "SystemLogin",
"Authenticationtype" : "Windows",
"Roles":[ "bulkadmin", "setupadmin", "diskadmin" ],
"Pages":["SignUp","Login","ForgotPassword"]
}'
select LoginName,AuType,PageName,RoleName from OPENJSON(#json)
WITH
(
LoginName VARCHAR(20) '$.LoginName' ,
AuType VARCHAR(20) '$.Authenticationtype',
Pages nvarchar(MAX) '$.Pages' AS JSON,
Roles nvarchar(MAX) '$.Roles' AS JSON
)
CROSS APPLY OPENJSON(Pages) WITH
(
PageName VARCHAR(20) '$'
)
CROSS APPLY OPENJSON(Roles) WITH
(
RoleName VARCHAR(20) '$'
)
Here is OutPut
I want Expected Result
You need to use OPENJSON() with default schema when you parse $.Pages and $.Roles JSON arrays:
JSON:
DECLARE #json NVarChar(max)='{
"LoginName" : "SystemLogin",
"Authenticationtype" : "Windows",
"Roles":[ "bulkadmin", "setupadmin", "diskadmin" ],
"Pages":["SignUp","Login","ForgotPassword"]
}'
Statement:
SELECT LoginName, AuType, p.[value] AS PageName, r.[value] AS RoleName
FROM OPENJSON(#json) WITH (
LoginName VARCHAR(20) '$.LoginName' ,
AuType VARCHAR(20) '$.Authenticationtype',
Pages nvarchar(MAX) '$.Pages' AS JSON,
Roles nvarchar(MAX) '$.Roles' AS JSON
)
OUTER APPLY OPENJSON(Pages) p
OUTER APPLY OPENJSON(Roles) r
WHERE p.[key] = r.[key]
Result:
LoginName AuType PageName RoleName
----------------------------------------------
SystemLogin Windows SignUp bulkadmin
SystemLogin Windows Login setupadmin
SystemLogin Windows ForgotPassword diskadmin
..plagiarizing.. upvote the original author/source (#Zhorov)
DECLARE #json NVarChar(max)='{
"LoginName" : "SystemLogin",
"Authenticationtype" : "Windows",
"Roles":[ "bulkadmin", "setupadmin", "diskadmin" ],
"Pages":["SignUp","Login","ForgotPassword", "Page1", "Page2"]
}';
/*
"Roles":[ "bulkadmin", "setupadmin", "diskadmin", "Role1", "Role2", "Role3" ],
"Pages":["SignUp","Login","ForgotPassword"]
*/
/*
"Roles":[],
"Pages":[]
*/
SELECT LoginName, AuType, pr.PageName, pr.RoleName
FROM OPENJSON(#json) WITH (
LoginName VARCHAR(20) '$.LoginName' ,
AuType VARCHAR(20) '$.Authenticationtype',
Pages nvarchar(MAX) '$.Pages' AS JSON,
Roles nvarchar(MAX) '$.Roles' AS JSON
) as oj
outer apply
(
select p.value as PageName, r.value as RoleName
from
(
select *
from OPENJSON(oj.Pages)
) as p
full outer join
(
select *
from OPENJSON(oj.Roles)
) as r on p.[key] = r.[key]
) as pr;
Given the sample json data below, how can I write a query to pull the array data all in one step to individual column?
DECLARE #json NVARCHAR(MAX);
SET #json = N'{
"Title":"ReportExport",
"Attachment":"",
"Name":"Dhoni",
"FirstTextArea":"Dhoni",
"Radio":"First",
"CheckBox":"{C++~.Net}",
"FileUpload":"",
"FirstGroupitem":[
{
"Address":"QTUvNU55THBxT2hmVXFkWGpia2NJQT09",
"Age":"30",
"TestField":"",
"Country":"ind",
"SecondTextArea":"11"
},
{
"Address":"OVpuaXpxNTlrZWg4dGI4VXRYMUg0Zz09",
"Age":"30",
"TestField":"",
"Country":"us",
"SecondTextArea":"22"
},
{
"Address":"WGErNFU2S0tYekdsRWZTT2NxSzZLQT09",
"Age":"30",
"TestField":"",
"Country":"us",
"SecondTextArea":"33"
}
],
"SecondGroupitem":[
{
"Address1":"QTUvNU55THBxT2hmVXFkWGpia2NJQT09",
"Age1":"30"
},
{
"Address1":"OVpuaXpxNTlrZWg4dGI4VXRYMUg0Zz09",
"Age1":"30"
}
]
}';
Statement:
SELECT i.Title,i.Attachment,i.Name,i.FirstTextArea,i.Radio,i.CheckBox,i.FileUpload,'FirstGroupitem' as FirstGroupitem,
a.Address, a.Age,a.TestField,a.Country,a.SecondTextArea
FROM OPENJSON(#json)
WITH (
Title VARCHAR(max) N'$.Title',
Attachment VARCHAR(max) N'$.Attachment',
Name VARCHAR(max) N'$.Name',
FirstTextArea VARCHAR(max) N'$.FirstTextArea',
Radio VARCHAR(max) N'$.Radio',
CheckBox VARCHAR(max) N'$.CheckBox',
FileUpload VARCHAR(max) N'$.FileUpload',
FirstGroupitem nvarchar(max) '$.FirstGroupitem' AS JSON
) AS i
CROSS APPLY (
SELECT *
FROM OPENJSON(i.FirstGroupitem)
WITH (
Address VARCHAR(max) N'$.Address',
Age VARCHAR(max) N'$.Age',
TestField VARCHAR(max) N'$.TestField',
Country VARCHAR(max) N'$.Country',
SecondTextArea VARCHAR(max) N'$.SecondTextArea'
)
) a
I want output like this:
You need to join the items from the $.FirstGroupitem" and $."SecondGroupitem JSON arrays by index:
Statement:
SELECT
i.Title, i.Attachment, i.Name, i.FirstTextArea, i.Radio, i.CheckBox,
j.FirstGroupAddress, j.SecondGroupAddress
FROM OPENJSON(#json)
WITH (
Title VARCHAR(max) N'$.Title',
Attachment VARCHAR(max) N'$.Attachment',
Name VARCHAR(max) N'$.Name',
FirstTextArea VARCHAR(max) N'$.FirstTextArea',
Radio VARCHAR(max) N'$.Radio',
CheckBox VARCHAR(max) N'$.CheckBox',
FileUpload VARCHAR(max) N'$.FileUpload',
FirstGroupitem nvarchar(max) '$.FirstGroupitem' AS JSON,
SecondGroupitem nvarchar(max) '$.SecondGroupitem' AS JSON
) AS i
OUTER APPLY (
SELECT f2.Address AS FirstGroupAddress, s2.Address AS SecondGroupAddress
FROM OPENJSON (i.FirstGroupitem) f1
FULL JOIN OPENJSON (i.SecondGroupitem) s1 ON f1.[key] = s1.[key]
OUTER APPLY OPENJSON(f1.[value]) WITH (
Address varchar(100) '$.Address'
-- Additional columns here
) f2
OUTER APPLY OPENJSON(s1.[value]) WITH (
Address varchar(100) '$.Address1'
-- Additional columns here
) s2
) j
Result:
Title Attachment Name FirstTextArea Radio CheckBox FirstGroupAddress SecondGroupAddress
---------------------------------------------------------------------------------------------------------------------------------
ReportExport Dhoni Dhoni First {C++~.Net} QTUvNU55THBxT2hmVXFkWGpia2NJQT09 QTUvNU55THBxT2hmVXFkWGpia2NJQT09
ReportExport Dhoni Dhoni First {C++~.Net} OVpuaXpxNTlrZWg4dGI4VXRYMUg0Zz09 OVpuaXpxNTlrZWg4dGI4VXRYMUg0Zz09
ReportExport Dhoni Dhoni First {C++~.Net} WGErNFU2S0tYekdsRWZTT2NxSzZLQT09
I just want to receive a json data and use it's fields as a table column for another queries.
I'm trying to make the value in the key "nameProperty" into a column in a table, and the value of the keys "newValue"fill the rows of that column.
For example:
i get a json file like this
{
"operation":{
"ID":"ABC",
"KinshipDescription":"--"
},
"fields":[
{
"property":{
"nameProperty":"ID",
"oldValue":"",
"newValue":"123456",
"confirmed":"false",
"labelProperty":"ID",
"oldValueDescription":"",
"newValueDescription":"123456"
}
},
{
"property":{
"nameProperty":"Name",
"oldValue":"",
"newValue":"John",
"confirmed":"false",
"labelProperty":"Name",
"oldValueDescription":"",
"newValueDescription":"John"
}
}
]
}
I want to extract the objects on the list "fields", but i only can make them an row for key, and another row for values like the script below makes.
DECLARE #jsonObj NVARCHAR(MAX)
--Set a result in
SET #jsonObj = (select JSON_Query(data, '$.fields') from table where id = 'ABC')
select * from openjson(#jsonObj)
with (Property nvarchar(255) '$.property.nameProperty',
newValue nvarchar(50) '$.property.newValue')
and I have no idea how I can do this
the results of this script is something like this
ID 123456
Name John
and the results that i want to see is
ID Name --column name, not a row
123456 John
The quickest (thought-wise, not necessarily performance) way I can come up with on this is using dynamic SQL. In fact, I'm pretty certain you'll have to use it.
Here's an example that can get you moving. You can run this in SSMS.
DECLARE #json NVARCHAR(MAX) =
'{
"operation":{
"ID":"ABC",
"KinshipDescription":"--"
},
"fields":[
{
"property":{
"nameProperty":"ID",
"oldValue":"",
"newValue":"123456",
"confirmed":"false",
"labelProperty":"ID",
"oldValueDescription":"",
"newValueDescription":"123456"
}
},
{
"property":{
"nameProperty":"Name",
"oldValue":"",
"newValue":"John",
"confirmed":"false",
"labelProperty":"Name",
"oldValueDescription":"",
"newValueDescription":"John"
}
}
]
}';
-- Variable to hold the column/values.
DECLARE #cols VARCHAR(MAX) = '';
-- Generate the column/value pairs.
SELECT
#cols = #cols
+ CASE WHEN ( LEN( #cols ) > 0 ) THEN ', ' ELSE '' END -- add comma if needed.
+ '''' + Properties.newValue + ''' AS [' + Properties.nameProperty + '] '
FROM OPENJSON( #json, '$.fields' ) WITH (
property NVARCHAR(MAX) '$.property' AS JSON
)
CROSS APPLY (
SELECT * FROM OPENJSON( property ) WITH (
nameProperty VARCHAR(50) '$.nameProperty',
oldValue VARCHAR(50) '$.oldValue',
newValue VARCHAR(50) '$.newValue',
confirmed VARCHAR(50) '$.confirmed',
labelProperty VARCHAR(50) '$.labelProperty',
oldValueDescription VARCHAR(50) '$.oldValueDescription',
newValueDescription VARCHAR(50) '$.newValueDescription'
)
) AS Properties;
-- Execute column/value pairs as dynamic SQL.
EXEC ( 'SELECT ' + #cols );
Which returns:
+--------+------+
| ID | Name |
+--------+------+
| 123456 | John |
+--------+------+
If you were to PRINT #cols you would see
'123456' AS [ID] , 'John' AS [Name]
A few quick notes:
Performance may vary.
Values are quoted but can be CAST if needed.
Included all 'property' fields in CROSS APPLY for example. Only specify what is needed.
Note the use of NVARCHAR when using AS JSON
May want to consider OUTER APPLY if there's potential for no 'property' present.
I have some json that I would like to parse in SQL Server 2016. There is a hierarchy structure of Projects->Structures->Properties. I would like to write a query that parses the whole hierarchy but I don't want to specify any elements by index number ie I don't want to do anything like this:
openjson (#json, '$[0]')
or
openjson (#json, '$.structures[0]')
I had this idea that I could read the values of the top level project objects along with the json string that represents the structures below it, which could then be parsed separately. The problem is that the following code does not work:
declare #json nvarchar(max)
set #json = '
[
{
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Project",
"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":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
},
{
"IdProperty":"FFF433EC-0BB5-41CD-8A71-B5F09B97C5FC",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 1",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
}
]
}
]
}
]';
select IdProject, Name, structures
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max)
) as Projects
IdProject and Name get returned no problem but for some reason I cannot get the nested json held in 'structures'. Instead of the json content it just returns NULL:
Does anyone know if this is possible and if so, what am I doing wrong?
Using CROSS APPLY:
declare #json nvarchar(max)
set #json = '
[
{
"IdProject":"97A76363-095D-4FAB-940E-9ED2722DBC47",
"Name":"Test Project",
"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":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
},
{
"IdProperty":"FFF433EC-0BB5-41CD-8A71-B5F09B97C5FC",
"IdStructure":"CB0466F9-662F-412B-956A-7D164B5D358F",
"Name":"Test Property 1",
"DataType":1,
"Precision":0,
"Scale":0,
"IsNullable":false,
"ObjectName":"Test Object",
"DefaultType":1,
"DefaultValue":""
}
]
}
]
}
]';
select
Projects.IdProject, Projects.Name as NameProject,
Structures.IdStructure, Structures.Name as NameStructure, Structures.BaseStructure, Structures.DatabaseSchema,
Properties.*
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
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
If you reference JSON object or array you need to specify AS JSON clause:
select IdProject, Name, structures
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) AS JSON
) as Projects
See FAQ: https://learn.microsoft.com/en-us/sql/relational-databases/json/solve-common-issues-with-json-in-sql-server?view=sql-server-ver15#return-a-nested-json-sub-object-from-json-text-with-openjson
If you want to apply OPENJSON on the returned structures array, you can use something like following code:
select IdProject, Name, structures
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) AS JSON
) as Projects
CROSS APPLY OPENJSON (structures) WITH (......)
Typical! I found the answer just after posting the question. You need to use the 'as json' key word when specifying the columns to return:
select IdProject, Name, structures
from openjson (#json)
with
(
IdProject uniqueidentifier,
Name nvarchar(100),
structures nvarchar(max) as json
) as Projects