Find stored procedure dependencies on MySql - mysql

I'm working on a 8.0.15 Mysql on which I have several stored procedures.
The "master" call the others, and every procedure may (or may not) call other procedures themselves
My goal is to have a "tree" of the procedures, to document the order on which they are called.
Any ideas on how to do so? I was thinking to query information_schema.ROUTINES tables, extract only the various Call with some regex to have only the "bone" of my procedures, something like:
MAIN_PROCEDURE
CALL PCD2();
CALL PCD3();
END;
PCD2
CALL PCD4();
END;
then, recursively do it in order to know that PCD4 is called inside PCD2.
I'm stuck on the first part, then the recursive query should be quite easy
Any help? Of course any other method is fine!
Thanks in advance

would like to know if there is an automatic way to deal with unbalanced data. Let's say it is a binary classification problem and I want to use cross-validation, for example kfolds.
Do you know if there is any cross-validation technique that does not only randomly shuffle the data, but also tries to "balance" the labels in the train set so it is 50%-50%?
That would help to not get high accuracy scores, just because the model has higher changes to learn more points from a particular class.

Try this code. Put your database name in "MyDataBase".
CREATE DEFINER=root#localhost PROCEDURE dependencias()
NO SQL;
BLOCK1:BEGIN
DECLARE bas, c1 VARCHAR(50);
DECLARE fin int DEFAULT FALSE;
DECLARE cur1 CURSOR FOR SELECT specific_name from information_schema.routines where routine_schema= bas;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fin = TRUE;
SET bas='MyDataBase';
DROP TABLE IF EXISTS dependencias;
CREATE TABLE dependencias (a varchar(50), b varchar(50));
OPEN cur1;
rulo1: LOOP
FETCH cur1 INTO c1;
IF fin THEN
LEAVE rulo1;
END IF;
BLOCK2: BEGIN
DECLARE can int;
DECLARE c2,cad varchar(50);
DECLARE fin int DEFAULT FALSE;
DECLARE cur2 CURSOR FOR SELECT specific_name from information_schema.routines where routine_schema= bas;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fin = TRUE;
OPEN cur2;
rulo2: LOOP
FETCH cur2 INTO c2;
IF fin THEN
LEAVE rulo2;
END IF;
SET cad=CONCAT ('%',c2,'(%');
SET can=(SELECT COUNT(*) FROM information_schema.routines WHERE Routine_Name = c1 AND routines.routine_definition LIKE cad AND Routine_Schema = bas);
IF c1!=c2 AND can>0 THEN
INSERT INTO `dependencias` values (c1,c2);
END IF;
END LOOP rulo2;
CLOSE cur2;
END BLOCK2;
END LOOP rulo1;
CLOSE cur1;
END BLOCK1

Related

How to work with mysql cursor when you are dealing with a huge number of columns?

I am writing a procedure to convert data from multiple smaller tables into a 'flat' table with many columns(~100).
I have a cursor defined which reads/joins data from smaller tables.
So far I have seen that 'fetch' semantics works with explicit variables in mysql. Is there a way where I can do something like: 'fetch * from cursor; followed by insert'?
Following is a sample (for single field insert).
How to deal if let's say temp and jsontable had 50 columns. (fetching into 50 explicit variables or is there a better way?)
[Oracle has something called 'BULK COLLECT']
CREATE PROCEDURE simpleproc_insert (OUT param1 INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
declare iden int;
declare msg JSON;
declare insertCursor cursor for select * from temp;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
open insertCursor;
read_loop: LOOP
FETCH insertCursor INTO iden,msg;
IF done THEN
LEAVE read_loop;
END IF;
insert into jsontable(jdoc) values(msg);
END LOOP;
close insertCursor;
END

mysql 5.7 cursor not returning any values

Mysql (version 5.7) cursor not working. I tried many times and checked online could not find what is wrong.
It is looping through correctly as many records in the currency table. But when I try to read from the cursor it is only returning null and not the actual values from the table currency. The currency table has data.
DROP PROCEDURE IF EXISTS proc2;
CREATE PROCEDURE proc2()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE code VARCHAR(255);
DECLARE myCursor CURSOR FOR SELECT code FROM currency;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN myCursor;
delete from dummy;
read_loop: LOOP
FETCH myCursor INTO code;
IF finished = 1 THEN
LEAVE read_loop;
END IF;
insert into dummy(name) values(code);
END LOOP read_loop;
CLOSE myCursor;
End;
At last, it worked with below change to the script. (i.e. after adding table alias.)
For some reason, the column I tried out 'code' expects an alias. Maybe a reserved keyword, not sure.
DECLARE myCursor CURSOR FOR SELECT c.code FROM currency c;

Cursor incorrect integer value error

I am trying to make my first cursor in MySQL and I am receiving an error. It says incorrect integer value. I was thinking this would grab the value in row one from column customer_Id, and store it into the IdValue variable. How do I code this correctly and fix this error?
DELIMITER $$
CREATE PROCEDURE CursorProcedure()
BEGIN
DECLARE IdValue int;
DECLARE myCursor CURSOR FOR
SELECT customer_Id FROM customers;
OPEN myCursor;
FETCH myCursor INTO IdValue;
CLOSE myCursor;
SELECT IdValue;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS CursorProcedure;
DELIMITER $$
CREATE PROCEDURE CursorProcedure()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE IdValue int;
DECLARE myCursor CURSOR FOR SELECT customer_Id FROM customers;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN myCursor;
read_loop: LOOP
FETCH myCursor INTO IdValue;
IF done THEN
LEAVE read_loop;
END IF;
--
-- YOU ARE IN YOUR READ LOOP
-- DO SOMETHING WITH IT HERE
--
END LOOP;
CLOSE myCursor;
END$$
DELIMITER ;
But in the "do something with it here", don't do a SELECT on it because it will generate multiple result sets. Do something meaningful.
Manual page on Cursors.
As an aside, cursors are rarely your friends. They are extremely slow. Use them in dire emergencies only.

MySQL procedure loop stops after one iteration

I am working on a MySQL procedure that creates a summary of one of my tables. The procedure retrieves a dataset and loops through it using a cursor. For each iteration of the loop, the procedure updates another table. The problem I'm having is the loop ends after a single iteration, event though I know that the query I'm running retrieves more than one row.
BEGIN
# Variable declaration section omitted for brevity
DECLARE cur CURSOR FOR SELECT
t.result_id,
t.athlete_id, t.`first`, t.middle, `last`, t.pref, t.birth,t.uss,
t.club_id,t.code,t.club_name,
t.meet_name,t.meet_id,t.`start`,t.`end`,
MIN(t.time) as time,t.age,t.type
FROM sometable t GROUP BY club_id ORDER BY time asc,t.start desc,club_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO result_id,athlete_id, first_name, middle, last_name, pref, birth,uss,
club_id,club_code,club_name,
meet_name,meet_id,start_date,end_date,
result_time,age,type;
IF done=1 THEN
LEAVE read_loop;
END IF;
SET last_time = result_time;
INSERT INTO toptimes(`result_id`,`club_id`,`agegroup`,`sex`,`distance`,`course`,`stroke`,`data`,`published`)
VALUES(result_id,club_id,AgeGroupID,sex,distance,course,stroke,json,0);
END LOOP read_loop;
CLOSE cur;
END
I'm not clear what the problem is. When I run the select query manually, I get back several rows. Is there a problem running an insert statement inside the loop?
Your code chunk looks good to me.
How do you know that it's running only one iteration (i'm not seeing any
print or select statement for debug purpose)?
Are you getting any error while executing the stored procedure?
I tried to replicate the similar code with "sakila" database (mysql sample db). It's working perfectly. Please check this sql code sample, if it helps you.
DROP PROCEDURE IF EXISTS usp_select_dummy_data ;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE usp_select_dummy_data()
BEGIN
-- Declare your variables
Declare _var_actor_id int default 0;
DECLARE _var_film_id int default 0;
-- Declare variable used for cursor and loop control
DECLARE done int;
DECLARE loop_counter INT DEFAULT 0;
-- Declare the cursor
DECLARE cur CURSOR FOR
SELECT
actor_id, film_id
FROM film_actor;
-- Declare handlers
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- Open the cursor
OPEN cur ;
-- Start the loop
read_loop: LOOP
FETCH cur
INTO _var_actor_id, _var_film_id ;
-- break out of the loop if
-- 1. if there is no rows or
-- 2. we've processed them all
IF done = 1 THEN
CLOSE cur ;
LEAVE read_loop ;
END IF;
-- Count the number of times looped
SET loop_counter = loop_counter + 1 ;
END LOOP read_loop ;
-- print the loop count
select loop_counter;
END

mysql stored proc is not working from mysqlworkbench or java code

I have written a stored proc in mysql when i am running it through hopper it is working fine but when i am trying to run it from mysql workbench or java it is not returning any result and also not showing any exception
I will request you to please help me on this
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `issueitem`()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE inventoryids INT DEFAULT 0;
DECLARE batch varchar(39);
DECLARE resultstr varchar(3000) DEFAULT '';
DECLARE exp DATE;
DECLARE mfgdate DATE;
DECLARE availableunit INT;
DECLARE quantity INT DEFAULT 100;
DECLARE oldest_date DATETIME;
DECLARE cur_count INT;
DECLARE que_size INT DEFAULT 0;
DECLARE curs CURSOR FOR SELECT inventoryid,batch,exp,availableunit FROM aashramdata.inventory where itemid=1 ORDER BY exp ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN curs;
SET cur_count=quantity;
read_loop: LOOP
FETCH curs INTO inventoryids,batch,exp,availableunit;
IF done THEN
LEAVE read_loop;
END IF;
SET que_size = que_size + availableunit;
IF cur_count >= availableunit THEN
set cur_count=cur_count-availableunit;
set resultstr=CONCAT(resultstr,batch,' - ',exp,' - ',availableunit,' - ');
update aashramdata.inventory set `availableunit`=0 where inventoryid=inventoryids;
END IF;
IF cur_count < availableunit THEN
update aashramdata.inventory set `availableunit`=availableunit-cur_count where inventoryid=inventoryids;
set resultstr=CONCAT(resultstr,batch,' - ',exp,' - ',availableunit-cur_count,' - ');
set cur_count=0;
END IF;
IF que_size >= quantity then
LEAVE read_loop;
END IF;
END LOOP;
CLOSE curs;
select resultstr;
END
Since the procedure is apparently syntactically valid, it's impossible to answer what the problem might be, without some knowledge of the data.
The easiest way to debug a stored procedure is by peppering it with unbounded SELECT statements (that is, selects that are not part of a subquery and not part of an INSERT ... SELECT or SELECT ... INTO) and then running it from the MySQL command line client, which handles multiple result sets from stored procedures much more gracefully than most graphical clients.
For example:
...
SET cur_count=quantity;
SELECT cur_count; -- add this
read_loop: LOOP
FETCH curs INTO inventoryids,batch,exp,availableunit;
SELECT inventoryids,batch,exp,availableunit; -- add this
SELECT done; -- add this
IF done THEN
...
When run from the command line client...
mysql> CALL issueitem();
...output will start rolling out of the console at you, showing you the internal values the procedure is encountering as it iterates the loop.
This, or other SELECT statements like this added elsewhere, will expose the internal variables and this should help you find the problem. You'll need to remove them before you call the procedure from code or even the GUI since the GUI may not handle them well -- it may start opening new tabs or splitting panes or just ignoring everything after the first SELECT.
Note that the last iteration of the loop, you may see the values from the previous iteration repeated since the failed read from the cursor may not reset the variables, but "done" will also transition from 0 to 1 indicating that the cursor has run out of rows and fired the CONTINUE HANDLER, so those values won't actually have been processed twice.