cancel
Showing results for 
Search instead for 
Did you mean: 

nested arrays in sa_rowgenerator with sp_parse_json

Baron
Participant
1,991

Hi, could anybody tell me whether it is possible to retrieve subelements from the below code, so that I can get 6 lines instead of 2 (so 3X Mouse and 3X Keyboard).

begin

declare MyJson long varchar;

select '{"products":

[{

"product_id": 5696214696104,

"product_name": "mouse",

"product_price": 13.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "Black"},

{"Body_Color":"Blue", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}

]},

{"product_id": 5696214696350,

"product_name": "keyboard",

"product_price": 20.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "White"},

{"Body_Color":"Blue", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}]}]}' into MyJson;

DROP VARIABLE IF EXISTS sql_array;

call sp_parse_json ('sql_array', MyJson);

select sql_array.products[[row_num]].product_id,

sql_array.products[[row_num]].product_name

from sa_rowgenerator(1, CARDINALITY(sql_array.products))

end;

Accepted Solutions (1)

Accepted Solutions (1)

Baron
Participant

Now it works!!!

begin

declare MyJson long varchar;

select '{"products":

[{

"product_id": 5696214696104,

"product_name": "mouse",

"product_price": 13.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "Black"},

{"Body_Color":"Blue", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}

]},

{"product_id": 5696214696350,

"product_name": "keyboard",

"product_price": 20.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "White"},

{"Body_Color":"Blue", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}]}]}' into MyJson;

DROP VARIABLE IF EXISTS sql_array;

call sp_parse_json ('sql_array', MyJson);

select x.row_num JsonIndex, sql_array.products[[x.row_num]].product_id,

sql_array.products[[x.row_num]].product_name,

((sql_array.products[[JsonIndex]]).product_colors[[y.row_num]]).Body_Color,

((sql_array.products[[JsonIndex]]).product_colors[[y.row_num]]).Cable_Color

from sa_rowgenerator(1, CARDINALITY(sql_array.products)) as x,

sa_rowgenerator(1, CARDINALITY(sql_array.products[[JsonIndex]].product_colors)) as y,

end;

Baron
Participant
0 Kudos

Unfortunately this function sp_parse_json works not always, and only as it wants to work!!

In my above code (in the answer) it works very fine, provided that the length of the product_colors array is the same among all products!

for example the below code doesn't work (the diefference is that I only removed one color set from the product mouse)

begin

declare MyJson long varchar;

select '{"products":

[{

"product_id": 5696214696104,

"product_name": "mouse",

"product_price": 13.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}

]},

{"product_id": 5696214696350,

"product_name": "keyboard",

"product_price": 20.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "White"},

{"Body_Color":"Blue", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}]}]}' into MyJson;

DROP VARIABLE IF EXISTS sql_array;

call sp_parse_json ('sql_array', MyJson);

select x.row_num JsonIndex, sql_array.products[[x.row_num]].product_id,

sql_array.products[[x.row_num]].product_name,

((sql_array.products[[JsonIndex]]).product_colors[[y.row_num]]).Body_Color,

((sql_array.products[[JsonIndex]]).product_colors[[y.row_num]]).Cable_Color

from sa_rowgenerator(1, CARDINALITY(sql_array.products)) as x,

sa_rowgenerator(1, CARDINALITY(sql_array.products[[JsonIndex]].product_colors)) as y,

end;

Is this a bug, or I became mad with this function?

Baron
Participant
0 Kudos

I assume then, that this function sp_parse_json is written only for hobby using and not intended to be used in productive systems.

VolkerBarth
Contributor
0 Kudos

A bold statement. Are you sure the problem is with sp_parse_json and not with your select statement?

FWIW, telling "Doesn't work" is usually not a helpful message: Do you get an error code (so which one?) or does the result set differ from your expectations (then how?)?

Baron
Participant
0 Kudos

Here I have 2 Problems:

1- Resolving big Numbers of type (Bigint) -- here the problem is with the function sp_parse_json (this is a blocker).

2- Retrieving subelements from arrays with different sizes, here the problem is not with sp_parse_json, but maybe with my sql statement (or maybe with the function sa_rowgenerator)!

Could you please try these both code snippets! why the second one doesn't work?

begin

declare MyJson long varchar;

select '{"products":

[{

"product_id": 5696214696104,

"product_name": "mouse",

"product_price": 13.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "Black"},

{"Body_Color":"Blue", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}

]},

{"product_id": 5696214696350,

"product_name": "keyboard",

"product_price": 20.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "White"},

{"Body_Color":"Blue", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}]}]}' into MyJson;

DROP VARIABLE IF EXISTS sql_array;

call sp_parse_json ('sql_array', MyJson);

select x.row_num JsonIndex, sql_array.products[[x.row_num]].product_id,

sql_array.products[[x.row_num]].product_name,

((sql_array.products[[JsonIndex]]).product_colors[[y.row_num]]).Body_Color,

((sql_array.products[[JsonIndex]]).product_colors[[y.row_num]]).Cable_Color

from sa_rowgenerator(1, CARDINALITY(sql_array.products)) as x,

sa_rowgenerator(1, CARDINALITY(sql_array.products[[JsonIndex]].product_colors)) as y,

end;

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

begin

declare MyJson long varchar;

select '{"products":

[{

"product_id": 5696214696104,

"product_name": "mouse",

"product_price": 13.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}

]},

{"product_id": 5696214696350,

"product_name": "keyboard",

"product_price": 20.5,

"product_colors":[

{"Body_Color":"Red", "Cable_Color": "White"},

{"Body_Color":"Blue", "Cable_Color": "Black"},

{"Body_Color":"Orange", "Cable_Color": "White"}]}]}' into MyJson;

DROP VARIABLE IF EXISTS sql_array;

call sp_parse_json ('sql_array', MyJson);

select x.row_num JsonIndex, sql_array.products[[x.row_num]].product_id,

sql_array.products[[x.row_num]].product_name,

((sql_array.products[[JsonIndex]]).product_colors[[y.row_num]]).Body_Color,

((sql_array.products[[JsonIndex]]).product_colors[[y.row_num]]).Cable_Color

from sa_rowgenerator(1, CARDINALITY(sql_array.products)) as x,

sa_rowgenerator(1, CARDINALITY(sql_array.products[[JsonIndex]].product_colors)) as y,

end;

VolkerBarth
Contributor

Well, I'm no hobbyist so I can try when I find the time to...

Baron
Participant
0 Kudos

As for the second snippet, I get an error message as follows:

Cannot convert nvarchar to varray

SQLCODE=-157, ODBC 3 State="070006"

VolkerBarth
Contributor

This seems to be a limitation when JSON arrays have different sizes, according to Mark's response here. So I can't tell what a workaround might look like... Possibly you would need to check whether product_colors is of type "nvarchar(32767)" (in case array sizes are different) or an array (calling exprtype will fail then), and further adjust your selection then...

Baron
Participant
0 Kudos

Thank you.

Because of those limitations we have to look for another solution.

VolkerBarth
Contributor

FWIW, I'm trying to figure out how to work around that - but I guess this might get rather weird...

Baron
Participant
0 Kudos

A workaround for the problem of arrays with multiple row numbers is possible, when I read the Array element of product_colors as nvarchar, and then apply the sp_parse_json function on this varchar, the problem is that I need to make a curosr running on each product (but at the end we can still live with it).

For the other problem with bigint there is no workaround, since we don't have influence on how the function sp_parse_json works.

VolkerBarth
Contributor
0 Kudos

Yes, you would probably need to modify the JSON beforehand by putting double commas around numeric values so they are parsed as strings, and you would need to casst them to numbers afterwards.

Baron
Participant
0 Kudos

Do you mean modifying the JSON as String (using REPLACE function or similar)?

This would be then a very big overhead specially if I am getting several thousands of products each with several subelements.

Actually our goal was saving resources and having better performance so that we decided to rely on the database internal functions, but after having so much workarounds then we lose our goal.

VolkerBarth
Contributor
0 Kudos

Do you mean modifying the JSON as String (using REPLACE function or similar)?

Yes, possibly a REGEX search for 10 and more decimal digits without trailing decimal points and without enclosing commas - and sadly SQL Anywhere does not have a regep_replace.

So I agree that a different approach (or possibly calling an external JS function) might be worthwhile...

fvestjens
Participant

Baron, can you let me know how you solved this multiple row numbers issue using a cursor? I have the same problem now and would like to know how you solved this.

Answers (0)