Issues building a stored procedure with a loop using MySQL - mysql

The following procedure did not update any rows. Is there an obvious mistake in the syntax? I'm new to MySQL
set autocommit = 0;
DROP procedure IF EXISTS update_fee;
delimiter //
CREATE PROCEDURE update_fee()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE t_fee_id int(10);
DECLARE t_pubco_id int(10);
DECLARE t_auditor_id int(10);
declare fiscal_period_end_id int(10);
declare t_fiscal_year int(4);
DECLARE t_audit_id int(10);
DECLARE cur1 CURSOR FOR SELECT fee_id, pubco_id, auditor_id, fiscal_period_end_id, fiscal_year
from a_fees;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO t_fee_id, t_pubco_id,
t_auditor_id , fiscal_period_end_id, t_fiscal_year;
IF done THEN
LEAVE read_loop;
END IF;
set t_audit_id = get_audit_id (t_pubco_id,
t_auditor_id,
concat('''', t_fiscal_year, '-',
(select concat(fiscal_period_end_month, '-', fiscal_period_end_day, ''''
)
from a_fiscal_period_end
where t_fiscal_period_end_id = a_fiscal_period_end.fiscal_period_end_id
), ''''
)
);
update a_fees set audit_id = t_audit_id;
END LOOP;
CLOSE cur1;
END;
delimiter ;

set autocommit = 0; mean that you must COMMIT your changes manually. Use START TRANSACTION and COMMIT or ROLLBACK.

Related

What is wrong in my query with MySql store procedure?

I am new to mysql store procedure. I want my store procedure to check date value in Field date and compare to current date. If current date is bigger than date value in table, I want to update value in field status_number to '0'.
Here is my query :
DELIMITER $$
DROP PROCEDURE IF EXISTS check_status$$
CREATE PROCEDURE check_status()
BEGIN
DECLARE dd DATE;
DECLARE bDone INT;
DECLARE Count INT;
DEClARE my_status CURSOR FOR SELECT dates FROM t_date;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
OPEN my_status;
SET bDone = 0;
REPEAT
FETCH my_status INTO dd;
IF (dd < DATE(NOW()))
UPDATE t_date SET (status_number) VALUES (1);
END IF;
UNTIL bDone END REPEAT;
CLOSE my_status;
END$$
DELIMITER ;
Error message :
Thank for answering.
DELIMITER $$
DROP PROCEDURE IF EXISTS check_status$$
CREATE PROCEDURE check_status()
BEGIN
DECLARE dd DATE;
DECLARE bDone INT;
DECLARE Count INT;
DEClARE my_status CURSOR FOR SELECT dates FROM t_date;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
OPEN my_status;
SET bDone = 0;
REPEAT
FETCH my_status INTO dd;
IF (dd < DATE(NOW()))
-- UPDATE t_date SET (status_number) VALUES (1);
UPDATE t_date SET status_number = 1;
END IF;
UNTIL bDone END REPEAT;
CLOSE my_status;
END$$
DELIMITER ;
Check it. its tested on mssql. I try to convert it for mysql but not tested on mysql but i hope it will works.
DELIMITER //
CREATE PROCEDURE check_status()
BEGIN
DECLARE NOT_FOUND INT DEFAULT 0;
DECLARE v_dd DATE;
-- DECLARE #bDone INT;
-- DECLARE #Count INT;
DECLARE v_name VARCHAR(50); -- database name
DECLARE v_path VARCHAR(256); -- path for backup files
DECLARE v_fileName VARCHAR(256); -- filename for backup
DECLARE v_fileDate VARCHAR(20); -- used for file name
DECLARE db_cursor CURSOR FOR
SELECTdates INTO v_dd
FROM t_date
OPEN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET NOT_FOUND = 1;db_cursor
-- SET #bDone = 0;
FETCH NEXT FROM; db_cursor INTO v_dd
WHILE NOT_FOUND = 0
DO
IF (v_dd < cast (Now() as date) )
Then
UPDATE t_date SET status_number = 1;
END IF;
FETCH NEXT FROM; db_cursor INTO v_dd
END WHILE;
CLOSE db_cursor;
END;
//
DELIMITER ;

MySQL cursor fetch NULL

Why both my variables output NULL? SELECT part of the cursor is working properly.
CREATE PROCEDURE p2()
BEGIN
# Account table
DECLARE accountid INT;
DECLARE accountname VARCHAR(1000);
# 1. cursor finished/done variable comes first
DECLARE done INT DEFAULT 0;
# 2. the curser declaration and select
DECLARE c_account_id_name CURSOR FOR SELECT
accountid,
accountname
FROM temp.test;
# 3. the continue handler is defined last
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE;
OPEN c_account_id_name;
SET accountid = 0;
SET accountname = '';
read_loop: LOOP
FETCH c_account_id_name
INTO accountid, accountname;
IF done
THEN
LEAVE read_loop;
END IF;
SELECT accountname;
END LOOP;
END;
Variable and select attribute in cursor can't be the same...it's a MySQL bug.
This will work
DROP PROCEDURE IF EXISTS p2;
DELIMITER $$
CREATE PROCEDURE p2()
BEGIN
# Account table
DECLARE v_accountidsome INT; #pay attention
DECLARE v_accountnameelst VARCHAR(1000); #pay attention
# 1. cursor finished/done variable comes first
DECLARE v_done INT DEFAULT FALSE;
# 2. the cursor declaration and select
DECLARE c_account_id_name CURSOR FOR SELECT
accountid, #pay attention
accountname #pay attention
FROM temp.test;
# 3. the continue handler is defined last
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET v_done = TRUE;
OPEN c_account_id_name;
read_loop: LOOP
FETCH c_account_id_name
INTO v_accountidsome, v_accountnameelst;
IF v_done
THEN
LEAVE read_loop;
END IF;
SELECT v_accountidsome;
SELECT v_accountnameelst;
END LOOP;
CLOSE c_account_id_name;
END $$
DELIMITER ;
CALL p2();
Find more here

Need help customizing mysql trigger

This is my current trigger:
DELIMITER $$
CREATE DEFINER=`root`#`127.0.0.1` TRIGGER `unique_visit_new_campaign` AFTER INSERT ON `unique_visit` FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE pixel_id int;
DECLARE campaign_id varchar(45);
DECLARE cur CURSOR FOR SELECT id FROM pixels;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO pixel_id;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT IGNORE INTO pixels_campaign (campaign_id , pixel_id , date) VALUES (NEW.campaign_id ,pixel_id, current_timestamp);
END LOOP;
CLOSE cur;
END
I need it to NOT TRIGGER when new.campaign_id is empty or equals to the string {campaign_id}
I tried using MySQL IF but with no success.
Also, It kinda auto increment even when there is a campaign id already (when it ignores). any way I can stop that from happening?
Did you try this?
DELIMITER $$
CREATE DEFINER=`root`#`127.0.0.1` TRIGGER `unique_visit_new_campaign` AFTER INSERT ON `unique_visit` FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE pixel_id int;
DECLARE campaign_id varchar(45);
DECLARE cur CURSOR FOR SELECT id FROM pixels;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
IF new.campaign = '' or new.campaign = '{campaign_id}' or new.campaign is null THEN
OPEN cur;
ins_loop: LOOP
FETCH cur INTO pixel_id;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT IGNORE INTO pixels_campaign (campaign_id , pixel_id , date) VALUES (NEW.campaign_id ,pixel_id, current_timestamp);
END LOOP;
CLOSE cur;
END IF
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 ;

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