How to parse json data in SQL Server 2012? - sql

I am using SQL Server 2012.I have been assigned a task where one of my column (JsonText) of table Sample contains json data. I want to pass parse that data and insert into columns of another table (Test). I searched on net 'openjson' is supported in SQL Server 2016. How to do in SQL Server 2012?
Table1 : Sample
Id JsonText Active
JsonText
webaddress?{'data':'{"PId": "XXXX","Status": "YES","Name":"XXX","Address":"XXXX","MobileNumber":"xxx"}'}
I am intrested only 'PID,Address,MobileNumber' columns not all.
Table Test structure like this
Id, PID, Address, MobileNumber

Isaac your code is not working with not quoted values e.g. {"isAuthorized":"false","customerID":null}. I fixed this and your function should look like this.
ALTER FUNCTION [dbo].[JSON_VALUE]
(
#JSON NVARCHAR(3000),
#column NVARCHAR(3000)
)
RETURNS NVARCHAR(3000)
AS
BEGIN
DECLARE #value NVARCHAR(3000);
DECLARE #trimmedJSON NVARCHAR(3000);
DECLARE #start INT;
DECLARE #end INT;
set #start = PATINDEX('%' + #column + '":%',#JSON) + LEN(#column) + 2;
SET #trimmedJSON = SUBSTRING(#JSON, #start, LEN(#JSON));
Set #end = CHARINDEX(',',#trimmedJSON);
SET #value = REPLACE(SUBSTRING(#trimmedJSON, 0, #end),'"','');
RETURN #value
END

I created a function compatible with SQL 2012 to take care of this
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Isaac Adams
-- Create date: 7/12/2018
-- Description: Give the JSON string and the name of the column from which you want the value
-- =============================================
CREATE FUNCTION JSON_VALUE
(
#JSON NVARCHAR(3000),
#column NVARCHAR(3000)
)
RETURNS NVARCHAR(3000)
AS
BEGIN
DECLARE #value NVARCHAR(3000);
DECLARE #trimmedJSON NVARCHAR(3000);
DECLARE #start INT;
DECLARE #length INT;
SET #start = PATINDEX('%' + #column + '":"%',#JSON) + LEN(#column) + 3;
SET #trimmedJSON = SUBSTRING(#JSON, #start, LEN(#JSON));
SET #length = PATINDEX('%", "%', #trimmedJSON);
SET #value = SUBSTRING(#trimmedJSON, 0, #length);
RETURN #value
END
GO

>>> at JSON_VALUE function, at PATINDEX('%", "%', #trimmedJSON);
remove space from '%", "%'
if your JSON value is like
'{"street":"street1","street2":"street232423"}'

You can use JSON_VALUE(ColumnName,'$.Path') for pairs Json in TSQL, for example:
select JSON_VALUE(webaddress,'$.data.PID') as 'PID',
JSON_VALUE(webaddress,'$.data.Status') as 'Status',
JSON_VALUE(webaddress,'$.data.Name') as 'Name'
from test

Related

Substring in SQL with from a pattern

I am struggling to substring and get the values in SQL.
I am having a JSON String like the following:
DECLARE #string varchar(max)= '[{"CustomFieldId":18,"FieldName":"ABCD","FieldType":"freeText","FieldValue":null,"Details":null,"Value":null,"RelationTable":null,"Isisible":true,"IsAdmin":false,"CreatedDate":null,"ModifiedDate":null,"LoggedInUser":"TESTUSER"},{"CustomFieldId":19,"FieldName":"Workdomain","FieldType":"freeText","FieldValue":null,"Details":null,"Value":null,"RelationTable":null,"IsVisible":true,"IsAdmin":false,"CreatedDate":null,"ModifiedDate":null,"LoggedInUser":"149645"},{"CustomFieldId":20,"FieldName":"TEST1234","FieldType":"freeText","FieldValue":"Sometest","Details":null,"Value":null,"RelationTable":null,"IsVisible":false,"IsAdmin":false,"CreatedDate":null,"ModifiedDate":null,"_listlovFields":[],"org4Values":[],"LoggedInUser":"TESTUSER"}]'
or it can also be like this:
DECLARE #string varchar(max) = '[{"CustomFieldId":20,"FieldName":"TEST1234","FieldType":"freeText","FieldValue":"Sometest","Details":null,"Value":null,"RelationTable":null,"IsVisible":false,"IsAdmin":false,"CreatedDate":null,"ModifiedDate":null,"LoggedInUser":"TESTUSER"}]'
Now from any one of them I need to get the 'FieldValue' of a particular 'CustomFieldId' with a particular 'FieldName' and where the FieldValue starts with a particular string.
Like, I am going to get these:
declare #propName varchar(max) = 'Test1234',
#customFieldId varchar(max) = 20,
#value varchar(max) = 'Some'
So, in this particular case, I need to get the FieldValue of customfield with CustomFieldId:"20", FieldName":"TEST1234" and where FieldValue starts with 'Some'.
The output simply needs be the string 'Sometest' as this is the FieldValue of CustomFieldId:"20"
Any help in this would be highly appreciated.
this is quite easy to solve when you install regex functions on your sql server. I've included the link where you can find them.
https://www.simple-talk.com/sql/t-sql-programming/clr-assembly-regex-functions-for-sql-server-by-example/
declare #CustomFieldId nvarchar(50)= '20'
declare #FieldName nvarchar(50) = 'TEST1234'
declare #FieldValueStartsWith nvarchar(50) = 'Some'
declare #input nvarchar(500)
select #input = '[{"CustomFieldId":20,"FieldName":"TEST1234","FieldType":"freeText","FieldValue":"Sometest","Details":null,"Value":null,"RelationTable":null,"IsVisible":false,"IsAdmin":false,"CreatedDate":null,"ModifiedDate":null,"LoggedInUser":"TESTUSER"}]'
declare #result nvarchar(500)
declare #expression nvarchar(200) = '.*"CustomFieldId":' + #CustomFieldId + ',"FieldName":"' + #FieldName + '".*"FieldValue":("' + #FieldValueStartsWith + '\w+").*'
select #result = dbo.RegExReplaceX(#expression,#input,'$1',dbo.RegExOptionEnumeration(0,0,0,0,1,0,0,0,0)) -- OPTION = FOR CASE SENSITIVE
if #result = #input SELECT NULL ELSE SELECT #RESULT

How to pass parameter value for a string that is inside Variable?

Can some one please help me how can I pass a Parameter value into a string that is inside a Variable
Ex:
DECLARE #STR VARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID=#ID'
Here I want to pass #ID as a parameter to Variable #STR
Use sp_executesql to value to the parameter this will also avoid sql injection. Try this
DECLARE #STR NVARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID=#ID'
exec sp_executesql #str,'#ID INT',#ID
Use this:
DECLARE #STR VARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID=' + CAST(#ID AS VARCHAR(50))
Here's one easy way:
DECLARE #STR VARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID=#ID'
SET #STR = REPLACE(#STR, '#ID', COALESCE(CAST(#ID AS varchar(31)),''))
And of course there are others. You could have used string concatenation when building #STR, or you could keep it the way it is and use a parameterized call to sp_executesql when you finally want to execute the string, assuming that's what you want to do with it.
You can write a query as:
DECLARE #ID int;
--to use sp_executesql sql statement must be a Unicode variable
DECLARE #STR nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
/* Build the SQL string.
as a best practice you should specify column names instead of writing *
*/
SET #STR =
N'SELECT Col1,Col2 FROM STUDENT WHERE STUDENT_ID=#ID';
SET #ParmDefinition = N'#ID Int';
/* Execute the string with the parameter value. */
SET #ID = 1;
EXECUTE sp_executesql #STR, #ParmDefinition,
#ID = #ID;
For simplicity you can also create a Store Procedure for it:-
Code in SQL
Create Proc [ProcedureName]
#ID As int
As
SELECT * FROM STUDENT WHERE STUDENT_ID=#ID
Calling a Store Procedure
[ProcedureName] 1
--Here replace "1" with your Id
DECLARE #STR VARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID='+#ID
should do

SQL extracting data from SQL column

I have SQL table JSON data into one of the columns. The column type is varchar max.
I have to extract the data from that column using sql. For example
{"RESPONSE":{"value":"<p>this is a test.....</p>","isAnswered":true}}'
I want to extract: this is a test.....
and get rid of all attributes and Nodes
I am very new to JSON. Fisrt time looking into it and lost
You can try this:
begin transaction
declare #string varchar(max)
declare #result varchar(max)
declare #response varchar(max)
set #string = '{"RESPONSE":{"value":["d"],"isAnswered":true}}'
set #response = SUBSTRING(#string, PATINDEX('%response%',#string), PATINDEX('%":{"value"%',#string) - PATINDEX('%response%',#string))
print #response
-- for html tags
DECLARE #htmlTags TABLE
(
ID INT IDENTITY(1,1),
htmlTag varchar(50)
);
INSERT INTO #htmlTags
VALUES
('<p>'),
('</p>'),
('<h1>'),
('</h1>'),
('"'),
('{'),
('}'),
(':'),
(','),
('value'),
('isAnswered'),
('true'),
('false'),
(' '),
('['),
(']')
;
SET #result = #string
DECLARE #temp varchar(max) = '';
WHILE #result != #temp
BEGIN
SET #temp = #result;
SELECT
#result = Replace(#result, htmlTag, '')
FROM
#htmlTags
;
END;
set #result = REPLACE(#result, #response, '')
print #result
rollback
I'm assuming that the structure of your JSON response is:
{"RESPONSE":{"value":"","isAnswered":true}}
EDIT: I recommend to insert all html tags and names (like ) into the htmlTags table to obtain the result you want since you cannot predict which one of them is going to appear in the json.
UPDATE: use this set #response = SUBSTRING(#string, PATINDEX('%response%',#string), PATINDEX('%":{"value"%',#string) - PATINDEX('%response%',#string)) so you can replace any kind of RESPONSE pattern in your json.
Hope it helps.

SQL substring of URL

I am trying to select a part of a url which is after a wildcard expression and before another expression using SQL Server 2008 R2.
I have a url like:
https%www.msn.com%2ftokenauth%mapserver%ftoken%aogvgkooo%json
or:
https%www.msn.com%2ftokenauth%mapserver%token=aogvgkooo%json.
How do I write a sql query to only show aogvgkooo? The url is stored in column called url.
Here is my select statement:
select REPLACE(REPLACE(url, 'token=', ''),'%json', '')
have you looked at SUBSTRING, CHARINDEX or PATINDEX functions? this site gives a good explanation of them:
http://social.technet.microsoft.com/wiki/contents/articles/17948.t-sql-right-left-substring-and-charindex-functions.aspx
and this one gives an example as well
http://sqlzoo.net/howto/source/u.cgi/tip238311/sqlserver
DECLARE #url varchar(100)
SET #url ='https%www.msn.com%2ftokenauth%mapserver%token=aogvgkooo%json'
SELECT Replace(Replace(Replace(#url,substring(#url,1,Patindex('%token=%',#url)-1),''),'token=',''),'%json','')
sql fiddler
A user-defined function might be a good choice.
create function findToken (
#url nvarchar(max),
#tag nvarchar(100),
#after nvarchar(100)
) returns nvarchar(max) as begin
declare #token nvarchar(max);
declare #start int = charindex(#tag,#url) + len(#tag);
declare #justPast int = charindex(#after,#url,#start);
if #start = len(#tag) or #justPast = 0
return NULL;
return substring(#url,#start,#justPast-#start)
end;
go
declare #url varchar(100);
set #url ='https%www.msn.com%2ftokenauth%mapserver%token=aogvgkooo%json';
select
dbo.findToken(#url,'token=','%json');
DECLARE #url nvarchar(255),
#startPos nvarchar(100),
#endPos nvarchar(100)
SET #url ='https%www.msn.com%2ftokenauth%mapserver%token=aogvgkooo%json'
SET #startPos = 'token%'
SET #endPos = '%json'
SELECT SUBSTRING(#url,CHARINDEX(#startPos,REPLACE (#url,'=','%'),0)+ LEN(#startPos) ,CHARINDEX(#endPos,REPLACE (#url,'=','%'),0)-(CHARINDEX(#startPos,REPLACE (#url,'=','%'),0)+ LEN(#startPos)))
More general approach:
DECLARE #s VARCHAR(100) = 'https%www.msn.com%2ftokenauth%mapserver%ftoken%aogvgkooo%json'
SELECT REVERSE(SUBSTRING(
REVERSE(#s),
CHARINDEX('%', REVERSE(#s)) + 1,
CHARINDEX('%', REVERSE(#s), CHARINDEX('%', REVERSE(#s)) + 1) -
CHARINDEX('%', REVERSE(#s)) - 1))
Reversing string, then take substring from first occurence of % till second occurence, then reversing again.

How to use IN Operator in SQL Server

How to use IN Operator in SQL Server
Here Is the table Structure
Create Table Sample(Id INT,Name Varchar(50))
While I am the Query like this I can get the Value
Select * FROM Sample WHERE Id IN ('74','77','79','80')
While I am executing the above Query I can't able to get the Records Related to that table getting error executing this error.
DECLARE #s VARCHAR(MAX)
SET #s='74','77','79','80'
Select * FROM Sample WHERE Id IN (#s)
You are using wrong way
use the following way
DECLARE #s VARCHAR(MAX)
DECLARE #d VARCHAR(MAX)
SET #s='74 , 77 , 79 , 80'
set #d = 'select * from arinvoice where arinvoiceid in('+#s+')'
exec (#d)
here IN operator use integers collection not string collection..
you should use a function which gives back a result set ( takes a csv format and returns a table)
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Splitt] (#String NVARCHAR(4000),
#Delimiter CHAR(1))
RETURNS #Results TABLE (
Items NVARCHAR(4000))
AS
BEGIN
DECLARE #Index INT
DECLARE #Slice NVARCHAR(4000)
SELECT #Index = 1
IF #String IS NULL
RETURN
WHILE #Index != 0
BEGIN
SELECT #Index = Charindex(#Delimiter, #String)
IF #Index <> 0
SELECT #Slice = LEFT(#String, #Index - 1)
ELSE
SELECT #Slice = #String
IF ( NOT EXISTS (SELECT *
FROM #Results
WHERE items = #Slice) )
INSERT INTO #Results
(Items)
VALUES (#Slice)
SELECT #String = RIGHT(#String, Len(#String) - #Index)
IF Len(#String) = 0
BREAK
END
RETURN
END
and now you can write :
DECLARE #s VARCHAR(MAX)
SET #s='74,77,79,80'
Select * FROM Sample WHERE Id IN (select items from dbo.Splitt(#s,','))
If you are using ADO.NET, you can avoid the magic string, just use SqlDataRecord.
Or if you are using SQL Server 2008, you can also avoid the magic string by using Table-Valued Parameter
Source: http://www.sommarskog.se/arrays-in-sql-2008.html