populating table in stored procedure, mysql - mysql

Can anyone shed light on why this will not loop through the function and populate the temp table? Ive tried a number of things and at best can only get the first value to populate. I'm trying to take a value and a ":" separated string (queried in this procedure) to populate a table so I can reference it in a larger query. The function SPLIT_STR works great on its own but I cant seem to increment value "a" so that it separates ALL values per field per value.
BEGIN
DECLARE platform_val VARCHAR(255);
DECLARE productName_val VARCHAR(255);
DECLARE no_more_rows BOOLEAN;
DECLARE num_rows INT DEFAULT 0;
DECLARE loop_cntr INT DEFAULT 0;
DECLARE str VARCHAR(255);
DECLARE a INT DEFAULT 1;
DECLARE cur1 CURSOR FOR SELECT
ProductName,
ProductPlatforms
FROM Feed
limit 10;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_rows = TRUE;
OPEN cur1;
select FOUND_ROWS() into num_rows;
the_loop: LOOP
FETCH cur1
INTO productName_val,
platform_val;
SET str = platform_val;
WHILE a< num_rows DO
SET str=SPLIT_STR(str,":",a);
insert into temp values (productName_val, str);
SET a=a+1;
END WHILE;
END LOOP the_loop;
END

This is the idea I came up with
CREATE PROCEDURE `col2lines`()
BEGIN
declare v_platform,v_productName,v_platformAll varchar(255) default null;
declare v_finished int default 0;
declare curs cursor for select ProductName,ProductPlatforms from Feed limit 10;
declare continue handler for not found set v_finished = 1;
drop temporary table if exists temp_table;
create temporary table temp_table (
productName varchar(255),
platform varchar(255)
);
open curs;
parent: LOOP
fetch curs into v_productName, v_platformAll;
if (v_finished = 1) then LEAVE parent; end if;
child: LOOP
set v_platform = substring_index(v_platformAll, '::', 1);
set #strlen = char_length(v_platform);
if (#strlen > 0) then
insert into temp_table values (v_productName, v_platform);
set v_platformAll = substr(v_platformAll, #strlen + 3);
iterate child;
end if;
LEAVE child;
END LOOP child;
iterate parent;
END LOOP parent;
close curs;
select * from temp_table;
END

Related

variable usage in nested cursors

I have a stored procedure snippet like this
CREATE DEFINER=`root`#`%` PROCEDURE `new_procedure`()
BEGIN
DECLARE c_id varchar(100) DEFAULT "";
DECLARE cursor1 CURSOR for select id from t1 where name like 's%';
OPEN cursor1;
get_t1: LOOP
FETCH cursor1 into c_id;
p:begin
declare cursor2 cursor for select id from t2 where cl_id=c_id;
open cursor2;
get_t2: loop
fetch project_cursor into p_id;
// perform some tasks
t:begin
declare cursor3 cursor for select id from t3 where pr_id=p_id;
open cursor3;
get_t3:loop
fetch cursor3 into t_id;
IF v_finished = 1 THEN
LEAVE get_t3;
END IF;
//perform some tasks
close cursor3;
select p_id;
end t;
end loop t2;
end p;
END LOOP t1;
END
here select statement is not displaying any data
when i write select under cursor 3 it is working.
did i made any mistake? anything I missed
Some basic logic has been added in your SP, Try it whether this is what you are expecting.
CREATE DEFINER=`root`#`%` PROCEDURE `new_procedure`()
BEGIN
DECLARE c_id VARCHAR(100) DEFAULT "";
DECLARE done1 BOOLEAN DEFAULT FALSE;
DECLARE cursor1 CURSOR FOR SELECT id FROM t1 WHERE name LIKE 's%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1=TRUE;
OPEN cursor1;
GET_T1: LOOP
FETCH cursor1 INTO c_id;
IF done1 THEN
LEAVE GET_T1;
END IF;
P:BEGIN
DECLARE p_id INT ; -- check which data types suits you, might be int
DECLARE done2 BOOLEAN DEFAULT FALSE;
DECLARE cursor2 CURSOR FOR SELECT id FROM t2 WHERE cl_id=c_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2=TRUE;
OPEN cursor2;
GET_T2: LOOP
FETCH cursor2 INTO p_id;
IF done2 THEN
LEAVE GET_T2;
END IF;
/* perform some task */
T:BEGIN
DECLARE t_id INT ; -- check which data types suits you, might be int
DECLARE done3 BOOLEAN DEFAULT FALSE;
DECLARE cursor3 CURSOR FOR SELECT id FROM t3 WHERE pr_id=p_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done3=TRUE;
OPEN cursor3;
GET_T3:LOOP
FETCH cursor3 INTO t_id;
IF done3 THEN
LEAVE GET_T3;
END IF;
/* perform some tasks */
#select p_id; -- don't know what you are doing with this
END LOOP GET_T3;
CLOSE cursor3;
SET done3=FALSE;
END T;
END LOOP GET_T2;
CLOSE cursor2;
SET done2= FALSE;
END P;
END LOOP GET_T1;
CLOSE cursor1;
SET done1= FALSE;
END

Using for loop in MySql data set

How to use for loop in MySQL data set ?
FOR x IN (SELECT column FROM table_name WHERE column_2 = input_val)
LOOP
sum_total := sum_total + x.column ;
END LOOP;
This is an example how I used to loop data set in oracle.
How can this be achieved in MySql ?
How about not looping at all. It's SQL after all.
SELECT SUM(`column`) total
FROM table_name
WHERE column_2 = <input_val>
Otherwise use CURSOR
Now, equivalent loop using CURSOR will look like
DELIMITER $$
CREATE PROCEDURE sp_loop(IN input_val INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE sum_current, sum_total INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT column1 FROM table_name WHERE column2 = input_val;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO sum_current;
IF done THEN
LEAVE read_loop;
END IF;
SET sum_total = sum_total + sum_current;
END LOOP;
CLOSE cur1;
SELECT sum_total;
END$$
DELIMITER ;
Here is SQLFiddle
DROP PROCEDURE IF EXISTS `foo`.`usp_cursor_example`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `foo`.`usp_cursor_example`(
IN name_in VARCHAR(255)
)
READS SQL DATA
BEGIN
DECLARE name_val VARCHAR(255);
DECLARE status_update_val VARCHAR(255);
-- Declare variables used just for cursor and loop control
DECLARE no_more_rows BOOLEAN;
DECLARE loop_cntr INT DEFAULT 0;
DECLARE num_rows INT DEFAULT 0;
-- Declare the cursor
DECLARE friends_cur CURSOR FOR
SELECT
name
, status_update
FROM foo.friend_status
WHERE name = name_in;
-- Declare 'handlers' for exceptions
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET no_more_rows = TRUE;
OPEN friends_cur;
select FOUND_ROWS() into num_rows;
the_loop: LOOP
FETCH friends_cur
INTO name_val
, status_update_val;
IF no_more_rows THEN
CLOSE friends_cur;
LEAVE the_loop;
END IF;
select name_val, status_update_val;
-- count the number of times looped
SET loop_cntr = loop_cntr + 1;
END LOOP the_loop;
-- 'print' the output so we can see they are the same
select num_rows, loop_cntr;
END
DELIMITER ;

Can an inner loop in a mysql procedure use the result of the outer loop

I have tried to create the following procedure in mysql
PROCEDURE fix()
BEGIN
DECLARE event_id_ INT;
DECLARE gate_number INT;
DECLARE l_done INT DEFAULT 0;
DECLARE curs_event_id CURSOR FOR SELECT DISTINCT event_id FROM history_15min;
DECLARE curs_gate_number CURSOR FOR SELECT DISTINCT gate_number
FROM history_15min WHERE event_id =event_id_;
( -- HERE IS THE PROBLEM - event_id_ IS BLANK THERE FOR THE INNER LOOP RETURNS NO RESULTS ....)
DECLARE CONTINUE HANDLER FOR NOT FOUND SET l_done=1;
OPEN curs_event_id;
event_loop : LOOP
FETCH curs_event_id INTO event_id_;
IF l_done=1 THEN LEAVE event_loop;
END IF;
OPEN curs_gate_number;
gate_loop : LOOP
FETCH curs_gate_number INTO gate_number;
IF l_done=1 THEN LEAVE gate_loop;
END IF;
insert into t value ('1');
END LOOP gate_loop;
CLOSE curs_gate_number;
SET l_done=0;
END LOOP event_loop;
CLOSE curs_event_id;
END
Is there a way i can get the result from the first loop to be a variable in the second loop ??
Thank CHill60 , your link had the answer i was looking for
here is the correct way to perform the nested loop :
PROCEDURE fix()
BLOCK1: BEGIN
DECLARE colA_ INT;
DECLARE l_done INT DEFAULT 0;
DECLARE curs_colA CURSOR FOR SELECT DISTINCT colA FROM tableA;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET l_done=1;
OPEN curs_colA;
first_loop : LOOP
FETCH curs_colA INTO colA_;
IF l_done=1 THEN LEAVE first_loop;
END IF;
BLOCK2: BEGIN
DECLARE calB_ INT;
DECLARE l_done INT DEFAULT 0;
DECLARE curs_calB CURSOR FOR SELECT DISTINCT calB FROM tableB WHERE colA = colA_;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET l_done=1;
OPEN curs_calB;
second_loop : LOOP
FETCH curs_calB INTO calB_;
IF l_done=1 THEN LEAVE second_loop;
END IF;
insert into tmp value ('1');
END LOOP second_loop;
CLOSE curs_calB;
SET l_done=0;
END BLOCK2;
END LOOP first_loop;
CLOSE curs_colA;
END BLOCK1

mySQL (stored procedure) cursor infinite loop on last row

I have following code: Problem is on the last row of creature_y loop doesn't end and inserts same values (with increased guid) infinitely.
I tried few ways with changing continue handler but seems it is not that.
DELIMITER $$
DROP PROCEDURE IF EXISTS creature_copy
$$
CREATE PROCEDURE creature_copy ()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE new_guid INT(10);
-- Creature definition
DECLARE y_guid INT(10);
DECLARE y_id mediumint(8);
DECLARE y_map int(5);
DECLARE y_modelid mediumint(8);
DECLARE y_position_x float(10);
DECLARE y_position_y float(10);
DECLARE y_position_z float(10);
DECLARE y_orientation float(10);
DECLARE y_spawntimesecs INT(10);
DECLARE y_curhealth INT(10);
DECLARE y_curmana INT(10);
DECLARE y_MovementType tinyint(3);
-- waypoints definition
DECLARE w_id INT(10);
DECLARE w_point mediumint(8);
DECLARE w_position_x float(10);
DECLARE w_position_y float(10);
DECLARE w_position_z float(10);
DECLARE w_orientation float(10);
-- Generate creatures map
DECLARE creature_sel CURSOR FOR
SELECT guid,id, map, modelid, position_x, position_y, position_z, orientation, spawntimesecs, curhealth, curmana, MovementType
FROM creature_y;
-- Generate waypoints map
DECLARE waypoint_sel CURSOR FOR
SELECT id, point, position_x, position_y, position_z, orientation
FROM creature_movement
WHERE creature_movement.id = y_guid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN creature_sel;
-- Cleanup tables before re-running
TRUNCATE creature_t;
TRUNCATE waypoint_data;
-- Set starting guid before loop
SET new_guid = 504115;
creature_loop:LOOP
if done = 1 THEN
-- set done = 0;
CLOSE creature_sel;
LEAVE creature_loop;
end if;
SET new_guid = new_guid + 1;
FETCH creature_sel INTO y_guid, y_id, y_map, y_modelid, y_position_x, y_position_y, y_position_z, y_orientation, y_spawntimesecs, y_curhealth, y_curmana, y_MovementType;
INSERT INTO creature_t(guid, id, map, modelid, position_x, position_y, position_z, orientation, spawntimesecs, curhealth, curmana, MovementType) VALUES(new_guid, y_id, y_map, y_modelid, y_position_x, y_position_y, y_position_z, y_orientation, y_spawntimesecs, y_curhealth, y_curmana, y_MovementType);
OPEN waypoint_sel;
waypoint_loop:LOOP
FETCH waypoint_sel INTO w_id, w_point, w_position_x, w_position_y, w_position_z, w_orientation;
IF done = 1 THEN
SET done = 0;
LEAVE waypoint_loop ;
END IF;
INSERT INTO waypoint_data(id, point, position_x, position_y, position_z, orientation) VALUES (new_guid, w_point, w_position_x, w_position_y, w_position_z, w_orientation);
END LOOP waypoint_loop;
CLOSE waypoint_sel;
END LOOP creature_loop;
CLOSE creature_sel;
END;
I have found solution to this.
To use 2 different continue handlers (to see whether cursor is at end) you need to split code into blocks
BLOCK1: BEGIN
DECLARE done INT DEFAULT 0;
-- First cursor
DECLARE sel CURSOR FOR
SELECT column
FROM table;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN sel;
sel_loop:LOOP
if done = 1 THEN
set done = 0;
CLOSE sel;
LEAVE sel_loop;
end if;
FETCH sel INTO variable1;
-- Do something in loop
-- Start second code-block
BLOCK2: BEGIN
DECLARE done2 INT DEFAULT 0;
-- define second cursor
DECLARE sel2 CURSOR FOR
SELECT column
FROM table
WHERE column = condition;
-- define second handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2 = 1;
-- now you can make second cursor loop and it will finish properly.
OPEN sel2;
sel2_loop:LOOP
FETCH sel2 INTO variable2;
IF done2 = 1 THEN
SET done2 = 0;
LEAVE sel2_loop ;
END IF;
-- do something in second loop
END LOOP waypoint_loop;
CLOSE waypoint_sel;
-- End your code blocks and close first loop / cursor
END BLOCK2;
END LOOP sel_loop;
CLOSE sel;
END BLOCK1

how to do a split on a sql table column

I have a table that stores some comma separated strings. Is there a way to write a sql to
return me a separate rows for each token string obtained by splitting across commas.
You can simply write and call a stored procedure
DELIMITER $$
DROP PROCEDURE IF EXISTS explode_table $$
CREATE PROCEDURE explode_table(bound VARCHAR(255))
BEGIN
DECLARE id INT DEFAULT 0;
DECLARE value TEXT;
DECLARE occurance INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE splitted_value INT;
DECLARE done INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT table1.id, table1.value
FROM table1
WHERE table1.value != '';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TEMPORARY TABLE IF EXISTS table2;
CREATE TEMPORARY TABLE table2(
`id` INT NOT NULL,
`value` VARCHAR(255) NOT NULL
) ENGINE=Memory;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO id, value;
IF done THEN
LEAVE read_loop;
END IF;
SET occurance = (SELECT LENGTH(value)
- LENGTH(REPLACE(value, bound, ''))
+1);
SET i=1;
WHILE i <= occurance DO
SET splitted_value =
(SELECT REPLACE(SUBSTRING(SUBSTRING_INDEX(value, bound, i),
LENGTH(SUBSTRING_INDEX(value, bound, i - 1)) + 1), ',', ''));
INSERT INTO table2 VALUES (id, splitted_value);
SET i = i + 1;
END WHILE;
END LOOP;
SELECT * FROM table2;
CLOSE cur1;
END; $$
-------------------
CALL explode_table(',');