Loop through JSON object in mysql function - mysql

I have a json object which has list of products under a bill. I want to write a mysql function for it which reads the data from the json and iterates over it one by one and inserts the same data to product and bill tables.
Here is my json object
{"billNo":16,"date":"2017-13-11 09:05:01","customerName":"Vikas","total":350.0,"fixedCharges":100,"taxAmount":25.78,"status":paid,"product":[{"productId":"MRR11","categoryId":72,"categoryName":"Parker Pen","cost":200,"quantity":2,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}},{"productId":"MRR12","categoryId":56,"categoryName":"Drawing Books","cost":150,"quantity":3,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}}]}
Here I have a mysql function which reads the data from the JSON
CREATE DEFINER=`mydb`#`%` FUNCTION `raiseOrder`(dataObject Json)
RETURNS bigint(11)
BEGIN
DECLARE billNo BIGINT(11) DEFAULT NULL;
DECLARE customerName VARCHAR(64);
DECLARE date datetime DEFAULT NOW();
DECLARE total Float(12,2);
DECLARE taxamt Float(12,2);
DECLARE fixedCharges Float(12,2);
DECLARE products json;
DECLARE productId bigint(15) DEFAULT NULL;
DECLARE categoryId bigint(11);
DECLARE cost float;
DECLARE categoryName varchar(64);
DECLARE quantity int default 0;
DECLARE supplierId bigint(11);
DECLARE supplierName varchar(128);
SET billNo = (SELECT JSON_EXTRACT(dataObject, "$.billNo"));
SET customerName = (SELECT JSON_EXTRACT(dataObject, "$.customerName"));
SET products = (SELECT JSON_EXTRACT(dataObject, "$.products"));
SET productId = (SELECT JSON_EXTRACT(products, "$[0].productId"));
RETURN 1;
END
Now with these lines
SET products = (SELECT JSON_EXTRACT(dataObject, "$.products"));
SET productId = (SELECT JSON_EXTRACT(products, "$[0].productId"));
I get the inner products json and the id of the 0th product. But I want a way to iterate over the array of the products.

You can use a WHILE loop in conjunction with JSON_LENGTH to achieve this:
DECLARE json, products, product VARCHAR(4000);
DECLARE i INT DEFAULT 0;
SELECT '{"billNo":16,"date":"2017-13-11 09:05:01","customerName":"Vikas","total":350.0,"fixedCharges":100,"taxAmount":25.78,"status":"paid","product":[{"productId":"MRR11","categoryId":72,"categoryName":"Parker Pen","cost":200,"quantity":2,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}},{"productId":"MRR12","categoryId":56,"categoryName":"Drawing Books","cost":150,"quantity":3,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}}]}
' INTO json;
SELECT json->"$.product" INTO products;
WHILE i < JSON_LENGTH(products) DO
SELECT JSON_EXTRACT(products,CONCAT('$[',i,']')) INTO product;
SELECT product;
SELECT i + 1 INTO i;
END WHILE;
You'll probably need to do more than simply 'SELECT product' though ;-)
NOTE: MySQL JSON functions were added in 5.7.8 so you'll need to check your MySQL version first.

Extension to this answer, and if you want to loop through the keys of json object, you can do this via this way
declare _keys int default 0;
declare i int default 0;
declare _current_key varchar(50) default '';
select JSON_KEYS(product) into _keys;
while i < JSON_LENGTH(_keys) do
select json_extract(json_unquote(_keys), concat('$[', i, ']')) into _current_key;
set i = i + 1;
end while;

Related

How to run CRUD in single procedure by using json?(T-SQL)

Procedure
ALTER PROCEDURE [dbo].[SpProductTsk]
(#json varchar(MAX))
AS
----insert---
BEGIN
DECLARE #SelectedProcedure varchar(max) = ''
IF #SelectedProcedure = 'SpProductIns'
BEGIN
INSERT INTO [dbo].[Product](ProductName, ProductCategory, InsertPersonId, InsertDate)
SELECT
p.productName, p.productCategory,
p.insertPersonId, GETDATE()
FROM
OPENJSON(#json)
WITH
(productName varchar(50) '$.ProductName',
productCategory varchar(50) '$.ProductCategory',
insertPersonId int '$.InsertPersonId',
insertDate datetime '$.InsertDate') AS p
----SELECT-----
IF #SelectedProcedure = 'SpProductSelect'
BEGIN
SELET p.productName, p.productCategory
FROM [dbo].[Product] AS p
FOR JSON PATH, ROOT('ProductDetails')
END
-----UPDATE-----
IF #SelectedProcedure = 'SpProductUpd'
BEGIN
DECLARE #ProductId int,
#ProductName varchar(50),
#ProductCategory varchar(50),
#InsertPersonId int
SELECT
#ProductId = p.productId,
#ProductName = p.productName,
#ProductCategory = p.productCategory,
#InsertPersonId = p.insertPersonId
FROM
OPENJSON (#Json)
WITH
(productId int '$.ProductId',
productName varchar(50) '$.ProductName',
productCategory varchar(50) '$.ProductCategory',
insertPersonId int '$.InsertPersonId') AS p
UPDATE [dbo].[Product]
SET productName = #ProductName,
productCategory = #ProductCategory,
insertPersonId = #InsertPersonId
WHERE ProductId = #ProductId
END
----Delete---
IF #SelectedProcedure = 'SpProductDel'
BEGIN
DECLARE #Id int
SELECT #Id = p.productId
FROM OPENJSON(#json)
WITH (productId int '$.ProductId') AS p
DELETE FROM [dbo].[Product]
WHERE ProductId = #Id
END
END
END
EXEC [dbo].[SpProductTsk] #json = '{
"SelectedProcedur":"SpProductIn",
"ProductName":"Mutton",
"ProductCategory":"Meat",
"InsertPersonId":"1",
"InsertDate":"" }'
SELECT * FROM product
Code compiles but shows 0 rows inserted
You would need to get the "SelectedProcedur" value from the json you pass into the stored procedure.
After to declare #SelectedProcedure set it to the "SelectedProcedur" value from the json you pass in.
DECLARE #SelectedProcedure VARCHAR(MAX) = '';
SET #SelectedProcedure = (
SELECT [value]
FROM [OPENJSON](#json)
WHERE [key] = 'SelectedProcedur'
);
You'll need to fix your if statements as well. All your code is inside the "IF #SelectedProcedure = 'SpProductIns'" block so none of the other if statements would ever get executed.
Before the line
----SELECT-----
add
END
and then remove one of the END at the bottom.

Get statistics from MySQL json rows [duplicate]

I have a json object which has list of products under a bill. I want to write a mysql function for it which reads the data from the json and iterates over it one by one and inserts the same data to product and bill tables.
Here is my json object
{"billNo":16,"date":"2017-13-11 09:05:01","customerName":"Vikas","total":350.0,"fixedCharges":100,"taxAmount":25.78,"status":paid,"product":[{"productId":"MRR11","categoryId":72,"categoryName":"Parker Pen","cost":200,"quantity":2,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}},{"productId":"MRR12","categoryId":56,"categoryName":"Drawing Books","cost":150,"quantity":3,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}}]}
Here I have a mysql function which reads the data from the JSON
CREATE DEFINER=`mydb`#`%` FUNCTION `raiseOrder`(dataObject Json)
RETURNS bigint(11)
BEGIN
DECLARE billNo BIGINT(11) DEFAULT NULL;
DECLARE customerName VARCHAR(64);
DECLARE date datetime DEFAULT NOW();
DECLARE total Float(12,2);
DECLARE taxamt Float(12,2);
DECLARE fixedCharges Float(12,2);
DECLARE products json;
DECLARE productId bigint(15) DEFAULT NULL;
DECLARE categoryId bigint(11);
DECLARE cost float;
DECLARE categoryName varchar(64);
DECLARE quantity int default 0;
DECLARE supplierId bigint(11);
DECLARE supplierName varchar(128);
SET billNo = (SELECT JSON_EXTRACT(dataObject, "$.billNo"));
SET customerName = (SELECT JSON_EXTRACT(dataObject, "$.customerName"));
SET products = (SELECT JSON_EXTRACT(dataObject, "$.products"));
SET productId = (SELECT JSON_EXTRACT(products, "$[0].productId"));
RETURN 1;
END
Now with these lines
SET products = (SELECT JSON_EXTRACT(dataObject, "$.products"));
SET productId = (SELECT JSON_EXTRACT(products, "$[0].productId"));
I get the inner products json and the id of the 0th product. But I want a way to iterate over the array of the products.
You can use a WHILE loop in conjunction with JSON_LENGTH to achieve this:
DECLARE json, products, product VARCHAR(4000);
DECLARE i INT DEFAULT 0;
SELECT '{"billNo":16,"date":"2017-13-11 09:05:01","customerName":"Vikas","total":350.0,"fixedCharges":100,"taxAmount":25.78,"status":"paid","product":[{"productId":"MRR11","categoryId":72,"categoryName":"Parker Pen","cost":200,"quantity":2,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}},{"productId":"MRR12","categoryId":56,"categoryName":"Drawing Books","cost":150,"quantity":3,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}}]}
' INTO json;
SELECT json->"$.product" INTO products;
WHILE i < JSON_LENGTH(products) DO
SELECT JSON_EXTRACT(products,CONCAT('$[',i,']')) INTO product;
SELECT product;
SELECT i + 1 INTO i;
END WHILE;
You'll probably need to do more than simply 'SELECT product' though ;-)
NOTE: MySQL JSON functions were added in 5.7.8 so you'll need to check your MySQL version first.
Extension to this answer, and if you want to loop through the keys of json object, you can do this via this way
declare _keys int default 0;
declare i int default 0;
declare _current_key varchar(50) default '';
select JSON_KEYS(product) into _keys;
while i < JSON_LENGTH(_keys) do
select json_extract(json_unquote(_keys), concat('$[', i, ']')) into _current_key;
set i = i + 1;
end while;

how to apply while loop for loop query in mysql

CREATE DEFINER=`root`#`localhost` PROCEDURE `test4`()
BEGIN
declare GroupArray text;
DECLARE i INT DEFAULT 0;
DECLARE loopcount INT DEFAULT 0;
declare GroupId varchar (5);
set GroupArray=(select group_concat(distinct groupId) from EventList_View);
SET loopcount = (SELECT LENGTH(GroupArray) -
LENGTH(REPLACE(GroupArray,',', '')));
select loopcount;
WHILE i <= loopcount DO
SET i = i + 1;
SET GroupId = (SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(GroupArray,
',', i),',', -1));
select GroupId;
END WHILE;
END
this is my query i am trying to apply while loop and i want get all groupId but GroupArray [1,2,3]i am getting value but in loop count i am getting 0 can any one please tell me where am doing wrong . why i am unable to get loop count null and why i am not getting value 1,2,3 for group

Not able to assign month,day and year into local variables in mysql stored procedure even though data is there

I have to extract day, month and year of a date into variable and then do some updation on table
Problem I am having is that though i am able to get the result set by the local fields alway appear null
Mysql query is
DECLARE ExistingRecordYear INT;
DECLARE ExistingRecordMonth INT;
DECLARE ExistingRecordDay INT;
DECLARE CountRecords SMALLINT;
SELECT COUNT(*) , ExistingRecordYear = YEAR(updatedon),
ExistingRecordMonth = MONTH(updatedon), ExistingRecordDay = DAY(updatedon)
FROM `transactions`
WHERE `issuer_id` = _issuer_id
AND `msisdn` = _msisdn ;
Though updatedon is not a nullable field and my count result is 1 but i am still seeing null in all three fields of month,year,and day
Please help me in it
In a select statement, you use := to assign variables, not =. In addition, you probably want your variables to have a prefix to distinguish them from columns. Something like:
DECLARE v_ExistingRecordYear INT;
DECLARE v_ExistingRecordMonth INT;
DECLARE v_ExistingRecordDay INT;
DECLARE v_CountRecords SMALLINT;
SELECT v_CountRecords := COUNT(*) , v_ExistingRecordYear := YEAR(updatedon),
v_ExistingRecordMonth := MONTH(updatedon), v_ExistingRecordDay := DAY(updatedon)
FROM `transactions`
WHERE `issuer_id` = _issuer_id AND `msisdn` = _msisdn ;

mysql cursor - select IDs in stament

It returns IDs as string, it returns only one row which it has first ID. "7,6,5" It returns only 7; How can we correct this problem?
CREATE DEFINER=`root`#`localhost`
PROCEDURE `GET_COMPANION`(IN paramEmployeeId INT)
BEGIN
DECLARE counter INTEGER DEFAULT 0;
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_companion varchar(100) DEFAULT "";
DECLARE v_companion_list varchar(100) DEFAULT "";
-- declare cursor for companion_id
DEClARE companion_cursor CURSOR FOR
SELECT companion_id FROM employee_has_companion ehc
WHERE ehc.employee_id = paramEmployeeId;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1;
OPEN companion_cursor;
get_companion: LOOP
FETCH companion_cursor INTO v_companion;
IF v_finished = 1 THEN
LEAVE get_companion;
END IF;
-- build companion list
SET v_companion_list = CONCAT(v_companion,",",v_companion_list);
END LOOP get_companion;
CLOSE companion_cursor;
SELECT * FROM companion co
LEFT JOIN citizenship ci
ON co.citizenship_id = ci.citizenship_id
WHERE co.companion_id IN( SUBSTRING(v_companion_list,
1,LENGTH(v_companion_list)-1));
END
You can use FIND_IN_SET(str,strlist) to check existence of a string in a list of comma separated values.
Change:
SELECT * FROM companion co
LEFT JOIN citizenship ci
ON co.citizenship_id = ci.citizenship_id
WHERE co.companion_id IN( SUBSTRING(v_companion_list,
1,LENGTH(v_companion_list)-1));
To:
SELECT * FROM companion co
LEFT JOIN citizenship ci
ON co.citizenship_id = ci.citizenship_id
WHERE FIND_IN_SET( co.companion_id, v_companion_list ) > 0;