How to Remove Whole Index of List in a JSON - mysql

I have a JSON Values Like This.
{
"CHEQUE":[
{
"Cheque_No":"1",
"Cheque_Date":"2018-05-30",
"Cheque_Amount":"10000",
"Bank_Name":"ICICI"
},
{
"Cheque_No":"2",
"Cheque_Date":"2018-05-30",
"Cheque_Amount":"20000",
"Bank_Name":"ICICI"
},
{
"Cheque_No":"2",
"Cheque_Date":"2018-05-30",
"Cheque_Amount":"20000",
"Bank_Name":"SBI"
}
]
}'
How can i Remove Entire Index of 2 in a CHEQUE list using the search key SBI for Bank name?.
I need to Do this is in Mysql Stored Procedure without Store Values in DB. This is what I have tried:
CREATE DEFINER = root # PROCEDURE SP_TEST(
IN ls_json JSON,
OUT Message VARCHAR(1000)
)
BEGIN
SELECT
JSON_REMOVE(
ls_json,
CONCAT('$.CHEQUE[0].Bank_Name[0]')
)
INTO ls_json;
#SELECT JSON_REMOVE(ls_json,JSON_SEARCH(ls_json,'ALL',
CONCAT('$.CHEQUE[0].Cheque_No[*]')))
INTO ls_json; #select
JSON_SEARCH(ls_json, 'one', 10000);
SELECT
ls_json;
END

One option:
DELIMITER //
CREATE PROCEDURE `SP_TEST` (
IN `_ls_json` JSON,
IN `_bank_name` VARCHAR(64)
)
BEGIN
DECLARE `_base` CHAR(11) DEFAULT '$.CHEQUE[*]';
DECLARE `_base_attr` CHAR(10) DEFAULT '.Bank_Name';
DECLARE `_element` VARCHAR(1024);
`_loop`: LOOP
SET `_element` :=
JSON_SEARCH(
`_ls_json`,
'one',
`_bank_name`,
NULL,
CONCAT(`_base`, `_base_attr`)
);
IF (`_element` IS NOT NULL) THEN
SET `_ls_json` :=
JSON_REMOVE(
`_ls_json`,
JSON_UNQUOTE(
REPLACE(`_element`, `_base_attr`, '')
)
);
ELSE
LEAVE `_loop`;
END IF;
END LOOP `_loop`;
SELECT JSON_PRETTY(`_ls_json`);
END//
DELIMITER ;
See db-fiddle.

Related

how do I Store json objects into mysql table using storedprocedure

I have a JSON like below:
[
{
"Label":"rm_sensor_combined",
"Data":"[{\"Label\":\"name\",\"Value\":\"esd001\",\"Type\":\"String\"},{\"Label\":\"dname\",\"Value\":\"esd\",\"Type\":\"String\"},{\"Label\":\"location\",\"Value\":\"here\",\"Type\":\"String\"},{\"Label\":\"kill\",\"Value\":\"yes\",\"Type\":\"String\"}]",
"Where":"[{\"Label\":\"ExternLineNo\",\"Value\":\"10\",\"Type\":\"String\"},{\"Label\":\"ExternReceiptKey\",\"Value\":\"20\",\"Type\":\"String\"},{\"Label\":\"SKU\",\"Value\":\"got it\",\"Type\":\"String\"}]",
"Option":"INSERT"
}
]
I would like to store them into a table using a store procedure, the table should look like the below:
Label
Data
Where
Option
rm_sensor_combined
data Json
Where Json
insert
any advice would be appreciated. Thanks
below is my stored procedure like:
CREATE PROCEDURE `sp_getSaveJsonData`(ajs_param json)
BEGIN
drop table if exists ToSaveTable;
CREATE TEMPORARY TABLE ToSaveTable (
`Label` LONGTEXT,
`Data` LONGTEXT,
`Where` LONGTEXT,
`Option` nvarchar(1000)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SELECT JSON_EXTRACT(ajs_param, '$[*]') INTO #LblArray;
SELECT JSON_LENGTH(#LblArray) INTO #jsonLength;
set #counter = 0;
while #counter < #jsonLength do
select json_extract(#LblArray, concat('$[',#counter,']')) into #rowData;
insert into fromJsonTable(`Label`, `Data`, `Where`, `Option`)
values( REPLACE(json_extract(#rowData, '$.Label'), '"', ''),
REPLACE(json_extract(#rowData, '$.Data'), '"', ''),
REPLACE(json_extract(#rowData, '$.Where'), '"', ''),
REPLACE(json_extract(#rowData, '$.Option'), '"', '')
);
set #counter = #counter + 1;
end while;
END

How to update multiple json object in one row?

Hello I work on JSON in MySQL. I bumped into trouble...
for example, I have data as below
{
1:{fan:0},
2:{fan:3},
3:{fan:4},
}
And I wish update every fan value to 6 : How to do this in MySQL statement?
My below statement gives "in this situation path expressions may not contain the * and ** tokens"
UPDATE mytable set json = JSON_REPLACE(json,'$.*."Fan"', 6);
Is there any simple way to achieve this ?
One option is to use a stored routine (Function). Modify the script as you need:
DROP FUNCTION IF EXISTS `update_json`;
DELIMITER //
CREATE FUNCTION `update_json` (
`json` JSON,
`key` CHAR(5),
`value` TINYINT
) RETURNS JSON
BEGIN
DECLARE `_keys` JSON DEFAULT JSON_KEYS(`json`);
DECLARE `_length_keys` TINYINT UNSIGNED DEFAULT JSON_LENGTH(`_keys`);
DECLARE `_current_key` TINYINT UNSIGNED DEFAULT 0;
DECLARE `_key` VARCHAR(10);
WHILE `_current_key` < `_length_keys` DO
SET `_key` := JSON_EXTRACT(`_keys`, CONCAT('$[', `_current_key`, ']')),
`json` := JSON_REPLACE(`json`, CONCAT('$.', `_key`,'.', `key`), `value`),
`_current_key` := `_current_key` + 1;
END WHILE;
RETURN `json`;
END//
DELIMITER ;
UPDATE `mytable`
SET `json` = `update_json`(`json`, '"fan"', 6);
See db-fiddle.

MySQL If Statement and Increment

I am having issues with a MySQL If statement that creates a group rank. here is the MySQL Statement:
SELECT EnCode, EnName, QuScore,
#scorerank := IF(#currathlete = EnCode, #scorerank + 1, 1),
#currathlete := EnCode
FROM ranking ORDER BY EnCode, QuScore DESC
It currently gives the following output
'1004277','Ashe','1628','1','1004277'
'1004277','Ashe','1309','1','1004277'
'1004277','Ashe','1263','1','1004277'
'1004277','Ashe','648','1','1004277'
'1004277','Ashe','645','1','1004277'
'1004277','Ashe','1628','1','1004277'
'1015934', 'Sabina', '544', '1', '1015934'
'1015934', 'Sabina', '455', '1', '1015934'
'1015934', 'Sabina', '276', '1', '1015934'
'1015934', 'Sabina', '216', '1', '1015934'
What it should be doing is incrementing each of the '1' numbers by one for each row that has the same code, and then starting from 1 again when it sees a different code number (1004277, then 1015934 in this case)
Any help is appreciated as i have followed a number of examples online using the above method but seem to hit the same issue a this point.
Try this way in stored Procedure:
drop PROCEDURE if EXISTS INCREMENTME;
create PROCEDURE INCREMENTME()
BEGIN
DECLARE OldEnNamevar VARCHAR(10) DEFAULT NULL;
DECLARE done INT DEFAULT FALSE;
DECLARE Encodevar VARCHAR(10);
DECLARE EnNamevar VARCHAR(10);
DECLARE QuScorevar VARCHAR(10);
DECLARE scorerankvar VARCHAR(10);
DECLARE currathalthletevar VARCHAR(10);
DECLARE countcode int(29) DEFAULT(1);
DECLARE counter int(20) default 0;
DECLARE get_cur CURSOR FOR select `Encode`,`EnName`,`QuScore`,`scorerank`,`currathalthlete` from tbl_ranking;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
drop table if exists temp_temptable;
create TEMPORARY table temp_temptable(Encodevar VARCHAR(50) NULL,EnNamevar VARCHAR(50) NULL,QuScorevar VARCHAR(50) NULL,scorerankvar VARCHAR(50) NULL,currathalthletevar VARCHAR(50) NULL,recordCount int(10) null);
OPEN get_cur;
REPEAT
set counter = counter + 1;
FETCH get_cur INTO Encodevar,EnNamevar,QuScorevar,scorerankvar,currathalthletevar;
if (OldEnNamevar = EnNamevar) THEN
set countcode = countcode +1;
ELSE
if(counter=1) then
set countcode = 1;
ELSE
set countcode = 0;
end if;
end if;
if (OldEnNamevar != EnNamevar) THEN
set countcode = 1;
end if;
if(OldEnNamevar=NULL) then
set countcode = 1;
end if;
insert into temp_temptable (Encodevar,EnNamevar,QuScorevar,scorerankvar,currathalthletevar,recordCount) values(Encodevar,EnNamevar,QuScorevar,scorerankvar,currathalthletevar,countcode);
set OldEnNamevar = EnNamevar;
UNTIL done END REPEAT;
select * from temp_temptable;
drop temporary table if exists temp_temptable;
CLOSE get_cur;
END
call the procedure like this:
call INCREMENTME();
Here's the result:
You have to initialize your variables, otherwise they are null (at least at the beginning of the session, probably not anymore if you run it twice), and your query will give strange results. Try
SELECT EnCode, EnName, QuScore,
#scorerank := IF(#currathlete = EnCode, #scorerank + 1, 1),
#currathlete := EnCode
FROM ranking, (select #currathlete := '', #scorerank := 0) init
ORDER BY EnCode, QuScore DESC

How to convert TSQL query into MYSQL query?

I have developed a function for split string in tsql but mysql don't have some built in functions. I needed to function in MYSQL as i am new in mysql. Function should accept 2 parameters
1. String to be split
2. separator (',' or whatever)
Kindly reply me.
i had found solution on the internet you can into that.
DELIMITER //
DROP FUNCTION IF EXISTS `splitAndTranslate` //
CREATE FUNCTION splitAndTranslate(str TEXT, delim VARCHAR(124))
RETURNS TEXT
DETERMINISTIC
BEGIN
DECLARE i INT DEFAULT 0; -- total number of delimiters
DECLARE ctr INT DEFAULT 0; -- counter for the loop
DECLARE str_len INT; -- string length,self explanatory
DECLARE out_str text DEFAULT ''; -- return string holder
DECLARE temp_str text DEFAULT ''; -- temporary string holder
DECLARE temp_val VARCHAR(255) DEFAULT ''; -- temporary string holder for query
-- get length
SET str_len=LENGTH(str);
SET i = (LENGTH(str)-LENGTH(REPLACE(str, delim, '')))/LENGTH(delim) + 1;
-- get total number delimeters and add 1
-- add 1 since total separated values are 1 more than the number of delimiters
-- start of while loop
WHILE(ctr<i) DO
-- add 1 to the counter, which will also be used to get the value of the string
SET ctr=ctr+1;
-- get value separated by delimiter using ctr as the index
SET temp_str = REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, ctr), LENGTH(SUBSTRING_INDEX(str, delim,ctr - 1)) + 1), delim, '');
-- query real value and insert into temporary value holder, temp_str contains the exploded ID
SELECT <real_value_column> INTO temp_val FROM <my_table> WHERE <table_id>=temp_str;
-- concat real value into output string separated by delimiter
SET out_str=CONCAT(out_str, temp_val, ',');
END WHILE;
-- end of while loop
-- trim delimiter from end of string
SET out_str=TRIM(TRAILING delim FROM out_str);
RETURN(out_str); -- return
END//
reference http://www.slickdev.com/2008/09/15/mysql-query-real-values-from-delimiter-separated-string-ids/
In mysql they they dont support some functionality like sqlserver. so spliting will be difficult in mysql
SELECT e.`studentId`, SPLIT(",", c.`courseNames`)[e.`courseId`]
FROM ..
SELECT TRIM(SUBSTRING_INDEX(yourcolumn,',',1)), TRIM(SUBSTRING_INDEX(yourcolumn,',',-1)) FROM yourtable
CREATE FUNCTION [dbo].[SplitString]
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
--Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select
Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END

Mysql WHERE IN (*)

I have a procedure A which takes an array of strings. By calling another procedure B, i break this array in this format:
'1','2','3','4'
In case there is only one value, it just displays as '1'
I want to return * in case the array passed to the procedure A.
Therefore, my query will be like this: select * from users where userId(*);
What i want is that in case the parameter is null, it should still perform the IN using.
** EDIT **
Nothing much of query
CREATE DEFINER=`root`#`localhost` PROCEDURE `listAll`(IN id varchar(200))
BEGIN
set #t = lib_explode(',',id);
select * from city where ID in(#t);
END
Procedure B
CREATE DEFINER=`root`#`localhost` FUNCTION `lib_explode`(sSepar VARCHAR(255), saVal TEXT) RETURNS varchar(200) CHARSET utf8
body:
BEGIN
IF sSepar IS NULL OR saVal IS NULL THEN LEAVE body; END IF;
SET #saTail = saVal;
SET #iSeparLen = LENGTH( sSepar );
set #mystring = '';
set #current_pos = 1;
create_layers:
WHILE #saTail != '' DO
# Get the next value
SET #sHead = SUBSTRING_INDEX(#saTail, sSepar, 1);
SET #saTail = SUBSTRING( #saTail, LENGTH(#sHead) + 1 + #iSeparLen );
-- INSERT INTO lib_Explode SET val = #sHead;
if(#current_pos > 1) then
set #mystring = concat(#mystring,',',concat("'",#shead,"'"));
else
set #mystring = concat(#mystring,concat("'",#shead,"'"));
end if;
set #current_pos = #current_pos + 1;
END WHILE;
return #mystring;
END