|
Nowadays JSON is a common, really helpful article
|
|
|
|
|
First, thanks for this script, really useful.
I found a bug. In these 2 functions (json_Value and json_Value2 ), they are supposed to return nvarchar(max), but on some error validations, you try to return a static string converted (cast) to int!?
For example:
if (@kind!='ARRAY') return cast('Using index in non array JSON' as int);
It should be (remove the cast to fix):
if (@kind!='ARRAY') return 'Using index in non array JSON';
Maybe you should check all functions for this kind of error. SQL don't like this when we fall in these cases.
Thanks.
modified 21-Jan-21 11:35am.
|
|
|
|
|
Hi,
It is not a bug, it is on purpose.
When the parser fails (ie: a non-numeric value has been entered as an array index or a numeric as a property value) and exception should be generated. However SQL doesn't allow to throw exceptions inside functions. This cast will generate an exception with a nice message.
More info at How to report an error from a SQL Server user-defined function - Stack Overflow.
Regards,
J
|
|
|
|
|
Jose, thanks for the article. Easy to understand and informative one, good job man!
Recently I studied the question of generating JSON data. There is a point of view that the easiest way is to use FOR JSON AUTO as it will generate the JSON object array where each row in the selection will be a separate object, while a column will be a property.
What do you think?
p.s. examples with code samples I found here: article about json data generation[^]
|
|
|
|
|
Hi,
Thanks for your comment !!
The FOR JSON is only for SQL Server 2016 and beyond. Honestly can't say much about it, as I haven't used it, but in principle this should be the easiest way (already built in), and I guess that the native support would cover the most common scenarios.
Kind regards,
|
|
|
|
|
anyone have any quick suggestions for making this work in sql 2008 which lacks the OFFSET command?
I get the following error in two functions (json_value and json_value2)
Quote: Msg 102, Level 15, State 1, Procedure json_Value, Line 31
Incorrect syntax near 'OFFSET'.
Msg 153, Level 15, State 2, Procedure json_Value, Line 31
Invalid usage of the option FIRST in the FETCH statement.
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[json_Value](@json nvarchar(max),@path nvarchar(max))
RETURNS nvarchar(MAX)
AS
BEGIN
declare @data pJsonData
declare @p1 TABLE(id int identity(1,1),name nvarchar(max))
insert into @data select id,parent,name,kind,value from dbo.json_Parse(@json)
set @path=ltrim(rtrim(@path))
if @path!='' insert into @p1(name) select * from dbo.ufn_Split(@path,'.')
declare @c0 int =0
declare @cur int =null
declare @step int =1
declare @max int =1
declare @v nvarchar(max)
declare @v2 nvarchar(max)
declare @kind nvarchar(max)
select @max=max(id) from @p1
select @c0=id,@cur=id, @kind=kind,@v=value from @data where parent=0 -- Current object is the one with parent =0
if @cur is null return null -- Should not happen
while (@step<=@max and @c0 is not null) begin
select @v=name from @p1 where id=@step
set @c0 =null
if (IsNumeric(@v)=1) begin
if (@kind!='ARRAY') return cast('Using index in non array JSON' as int);
set @v2=@v
SELECT @c0=ID,@cur=ID,@kind=kind,@v=value FROM @data where parent=@cur
ORDER BY ID OFFSET convert(int,@v) ROWS FETCH FIRST 1 ROW ONLY
end
else begin
if (@kind!='OBJECT') return cast('Using property name in a non-object JSON' as int);
SELECT @c0=ID,@cur=ID,@kind=kind,@v=value FROM @data where parent=@cur and name=@v
end
set @step=@step+1
end
if @c0 is null return null
if (@kind='OBJECT' or @kind='ARRAY') return dbo.json_toJson(@data,@cur)
return @v
END
|
|
|
|
|
This seems like it works:
-- sql 2012
-- SELECT @c0=ID,@cur=ID,@kind=kind,@v=value FROM @data where parent=@cur ORDER BY ID OFFSET convert(int,@v) ROWS FETCH FIRST 1 ROW ONLY
-- sql 2005 & 2008
;WITH results AS ( SELECT RowNumber = ROW_NUMBER() OVER( ORDER BY ID ASC ) , * FROM @data WHERE parent = @cur )
SELECT TOP 1 @c0=ID,@cur=ID,@kind=kind,@v=value FROM results WHERE RowNumber > convert(int,@v) ORDER BY RowNumber
|
|
|
|
|
At the end of the article you mention that Part 2 will (among other things) simplify query syntax.
Will Part 2 be ready anytime soon?
|
|
|
|
|
I have written half of it.
Are you interested ?? Sql 2016 supports JSON so I do not see much interest on this.
|
|
|
|
|
I would be interested in seeing part 2 (or whatever you have of it so far) as my company has not yet migrated to SQL 2016 (we are still on SQL 2012). We are working on migrating by the end of the year but we have a need for JSON support in SQL now.
|
|
|
|
|
Excellent article!
I noticed that this fails to parse json containing null values, although null is a part of the json spec (according to json.org).
For example, when I pass this json to dbo.json_Parse:
{"some":"value","aNullValue":null}
I get an error on the aNullValue node, it's kind is ERROR and the value is:
Unexpected token n
This is quite easy to fix, you just need to handle nulls in dbo.json_Item with something like:
-- Handle NULL
if (upper(substring(@json,@start,4))='NULL') begin
insert into @hierarchy(id,parent,name,kind,ppos,pend,value) values(@id,@parent,@name,'NULL',@start,@start+4,'')
return
end
|
|
|
|
|
Yes !!
You are right, I missed null-handling. I agree with your fix.
Thanks !!!
|
|
|
|
|
This also needed an update to the json_toJson() UDF as well:
if (@kind=''NULL'') begin
return ''null''
end
|
|
|
|
|
|
|
Very fast and very easy to implement.
|
|
|
|
|
Hi,
Could you update this part:
Quote: Although SQL Server has announced native JSON support for SQL Server 2016, currently this support is not publicly available.
JSON support is now publicly available. See more details in Friday the 13th - JSON is coming to SQL Server[^]
Thanks,
Jovan
|
|
|
|
|
Updated the SS 2016 reference.
Regards,
|
|
|
|
|
I want to convert any query statement or table in format pJsonData, Could you tell me which is the way to do this??
|
|
|
|
|
I have the same question. What's the point of this whole thing if you already have the JSON?
|
|
|
|
|
I've been looking at your code, can it read dynamic web-json such as from CartoDB? I'm interested in consuming JSON which is freqruently updated, and wrapping your code in a SQL Agent job which checks, say, every hour, access the JSON URL, and posts any new or changed JSON items into a SQL table.
|
|
|
|
|
Hi,
About your proposal, SQL is not a general purpose language, and the trickiest part is fetching the URL content from the SQL agent job. It can be done, either using CLR or "externalising" the fetching operation (curl, wget, or something similar) but configuration and passing the data to SQL is not going to be trivial.
I'd go for a C# solution to fetch the data and directly feed it to SQL. Once the JSON data gets into the SQL domain, you can use my code to parse it. After that its quite simple to compare with existig data and react on any change.
Regards,
|
|
|
|
|
Nicely written - thanks for posting this article.
|
|
|
|
|
|
Voted
==================!!!====================!!!========================
So much complexity in software comes from trying to make one thing do two things.
Kindest Regards
Sibeesh
http://sibeeshpassion.com/
|
|
|
|
|