Insert data into a table using OPENJson - sql

I have the following Json that needs to be inserted into a table
{"errorMessage":"","requestOutput":{ "REQUEST_ID" : 100910, "STATUS_CODE" : "P", "PHASE_CODE" :
"N", "COMPLETION_TEXT" : null }}
This is the query i am using to process the json and insert into the table
INSERT INTO dbo.tblRequest_Details([RequestId]
,[Error_Message]
,[Status_Code]
,[Phase_Code]
,[Completion_Text])
SELECT [RequestId]
,[Error_Message]
,[Status_Code]
,[Phase_Code]
,[Completion_Text]
FROM OPENJSON((select * from #json2), N'$.requestOutput')
WITH (
[RequestId] nvarchar(max) N'$.REQUEST_ID',
[Status_Code] nvarchar(max) N'$.STATUS_CODE',
[Phase_Code] nvarchar(max) N'$.PHASE_CODE',
[Completion_Text] nvarchar(max) N'$.COMPLETION_TEXT')
CROSS APPLY OPENJSON((select * from #json2), N'$.errorMessage')
WITH( [Error_Message] nvarchar(max) N'$.errorMessage'
)
But for some reason, data does not get inserted into the table.
What am I doing wrong?
Thanks

Turns out there was an error with the errorMessage field so I removed the cross apply. Instead assigned the value of errorMessage to a variable and used that instead.

Related

Select specific value from JSON list with SQL

Suppose I have a table column with person data organized as a JSON array, with categories and names.
In SQL, I can then easily select the data for a specific element in the array:
SELECT JSON_VALUE('{ "Persons": [{"PersonCat":"1","Name":"John"},{"PersonCat":"2","Name":"Henry"}]}','$.Persons[0].Name') AS SelectedPerson
I will then get "John".
But what if I want the person with "PersonCat" = 2? And null if PersonCat does not exist in the list?
I'm not sure it is possible to do this with the JSON_VALUE method, but it is possible using OPENJSON
DECLARE #json nvarchar(max)
SET #json = '{ "Persons": [{"PersonCat":"1","Name":"John"},{"PersonCat":"2","Name":"Henry"},{"Name":"Bob"}]}'
SELECT[PersonCat], [Name]
FROM OPENJSON(#json, '$.Persons')
WITH (
PersonCat NVARCHAR(512) '$.PersonCat',
[Name] NVARCHAR(512) '$.Name'
)
You can then add a WHERE clause to the SELECT to find the relevant PersonCat value (note: where the PersonCat property is missing from the array entry, the PersonCat column will be NULL)

How to get data from json column in SQL Server that starts with array element

I have a database table that I need to extract data from where the column of interest has json it. What makes this particularly difficult is the most outer elements of the json is '[' & ']' as in the parent element is an array. I need to get the value associated with key 'Name' (which in this case is 'MS220'). However, I'm not able to path correctly to the key I want.
The below JData table is a duplicate copy of the data I need to perform the extract on. Between SELECT OPENJSON, JSON_VALUE, JSON_QUERY etc., how can I retrieve the value I'm looking for?
Below is a couple of selects I've tried but not quite getting it.
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 *
FROM OPENJSON (JData,'$.[0]')
WITH (
[Name] varchar(10) '$.Name'
)
SELECT
JSON_VALUE(JData,'$') as v
#AaronBertrand: I had to modify the answer a little since the table also has a column labeled [name] as well. Is there a way to UPDATE ParamName to a new value?
SELECT
t.[Name],
ParamName
FROM
[myDB].[dbo].[myTable] t
CROSS APPLY
OPENJSON (t.params)
WITH
(
Categories nvarchar(max) AS json,
Id uniqueidentifier,
ParamName varchar(10) '$.Name'
);
SELECT Name FROM dbo.JData
CROSS APPLY OPENJSON (JsonData)
WITH
(
Categories nvarchar(max) AS json,
Id uniqueidentifier,
[Name] varchar(10)
);
Example db<>fiddle

How to pass a list of strings as a parameter in a stored procedure in SQL?

How to pass a list of strings as a parameter in a stored procedure in SQL?
Like for example if I have a stored procedure proc_aggregation that takes two parameters #Prod_Desc of varchar data type and another parameter #Prod_Code as a list of strings (Eg : #Prod_Code = ('12012', '12011', '12014')).
You will have to use table valued parameters
Define new type as follows
CREATE TYPE Prod_Code AS TABLE ( ProductCode varchar );
then use this type in your stored procedure
create procedure [dbo].[proc_aggregation]
#Prod_Code Prod_Code READONLY,
#Prod_Desc varchar (30)
as
......
Now before calling the stored procedure fill the table
declare #PC Prod_Code;
insert #PC VALUES ('12012'), ('12011'), ('12014')
Now Call the sp like this
EXEC dbo.proc_aggregation #PC, #Prod_Desc;
You can pass this data as varchar(max) parameter and then parse this string using string_split
Declare #Prod_Code VarChar(max) = '12012,12011,12014'
Select value As [Values]
From String_Split(#Prod_Code, ',')
or pass this data as a json array and parse this text using OPENJSON
Declare #Prod_Code VarChar(max) = '[12012, 12011, 12014]'
Select value As [Values]
From OPENJSON(#Prod_Code)
Values
12012
12011
12014
As an interesting fact, let'us compare performances of the different solutions... STRING, JSON, XML.
SET NOCOUNT ON;
GO
CREATE TABLE #test_list (id int identity primary key, style varchar(16), VAL VARCHAR(64), DT DATETIME2)
GO
-- JSON test
INSERT INTO #test_list VALUES ('JSON', '[12012, 12011, 12014]', SYSDATETIME());
GO
Select value As [Values]
From OPENJSON((SELECT VAL FROM #test_list WHERE style = 'JSON'));
GO 10000
-- STRING test
INSERT INTO #test_list VALUES ('STRING', '12012,12011,12014', SYSDATETIME());
GO
Select value As [Values]
From String_Split((SELECT VAL FROM #test_list WHERE style = 'STRING'), ',')
GO 10000
-- XML test
INSERT INTO #test_list VALUES ('XML', '<i v="12012" /><i v="12011" /><i v="12014" />', SYSDATETIME());
GO
WITH TX AS
(SELECT CAST(VAL AS xml) AS x
FROM #test_list AS i
WHERE style = 'XML')
Select y.value('(#v)[1]', 'varchar(16)')
From TX
CROSS APPLY x.nodes('/i') AS T(y);
GO 10000
-- final
INSERT INTO #test_list VALUES ('END', NULL, SYSDATETIME());
Executing the test without any dataset returned... (SSMS menu : Query/Options/Results/Grid/Ignore results after execution...)
Computing the execution time, is done by this query :
SELECT begins.style,
DATEDIFF(millisecond, begins.DT, ends.DT) AS DurationMS
FROM #test_list AS begins
JOIN #test_list AS ends ON begins.id = ends.id - 1
ORDER BY 2;
It is clear that string solution wins :
style DurationMS
---------------- -----------
STRING 2977
JSON 3358
XML 4242

Parse JSON in SQL

I'm looking to parse a single return in JSON into multiple rows.
The string is this -
{"policy_ids":["INZP2981-11000002","INZP-00001786","0AAAA01PC06"]}
I want to just parse this so that it is a row for each policy_ids. I've tried using OpenJSON WITH however I keep returning NULL values.
DECLARE #json NVARCHAR(MAX) ;
SET #json = N'{"policy_ids":["INZP2981-11000002","INZP-00001786","0AAAA01PC06"]}' ;
SELECT
*
FROM
OPENJSON(#json)
WITH (
policy_ids varchar(200) '$.policy_ids'
)
Help is appreciated.
You need a different statement to parse the $.policy_ids JSON array. You may try tou use OPENJSON() with default schema (without the WITH clause). In this case the result is a table with columns key, value and type and the value column returns the value of each item in the input array.
DECLARE #json NVARCHAR(MAX) ;
SET #json = N'{"policy_ids":["INZP2981-11000002","INZP-00001786","0AAAA01PC06"]}' ;
SELECT [value] AS policy_id
FROM OPENJSON(#json, '$.policy_ids')
Result:
policy_id
-----------------
INZP2981-11000002
INZP-00001786
0AAAA01PC06
If you want to use an explicit schema, the statement is:
SELECT *
FROM OPENJSON(#json, '$.policy_ids') WITH (
policy_id varchar(200) '$'
)

SQL - openjson to extract key from json

Below #json contains 3 data object within an array. After using OPENJSON to extract these objects to a Table variable, please see the output attached.
DECLARE #json NVARCHAR(MAX);
SET #json = N'[{"Container":"MSKU2913236","Seal":"ML-TH4773979","Size":"20","Temperature":"-20","TareWeight":"3.132","CreatedDate":"02-02-2018 00:00:00","Comment":null,"NetWeight":"21.445","TempRec#":null},{"Container":"MSKU3432702","Seal":"ML-TH4773972","Size":"20","Temperature":"-40","TareWeight":"2.872","CreatedDate":"02-02-2018 00:00:00","Comment":null,"NetWeight":"23.932","TempRec#":"TR12345"},{"Container":"MSKU4043053","Seal":"ML-TH4773973","Size":"20","Temperature":"-20","TareWeight":"2.995","CreatedDate":"02-02-2018 00:00:00","Comment":null,"NetWeight":"22.4","TempRec#":null}]';
DECLARE #ContainerTable TABLE(
[Key] NVARCHAR(100),
[Data] NVARCHAR(MAX)
);
INSERT INTO #ContainerTable
SELECT [key], [value] FROM OPENJSON(#json)
SELECT * FROM #ContainerTable
Output
Objective is to replace the Key column values with the Container property value from json in the Data column for all 3 rows.
Expected Output
Note: Expected output is hard coded and it only shows the one row but same is required for all rows.
You could use JSON_VALUE:
INSERT INTO #ContainerTable([Key], [Data])
SELECT JSON_VALUE([value],'$.Container'), [value]
FROM OPENJSON(#json);
DBFiddle Demo