error code #1064 while Declaring Cursor in MySQL - mysql

It's my first time working with cursors on MySQL, and I am having some problems, it doesn't accept the declaration of my cursor, what's wrong with my code? it shows me this error messagae:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'DECLARE #MyCursor CURSOR' at line 1
and my code is:
DECLARE #MyCursor CURSOR;
DECLARE #MyField varchar2(255);
BEGIN
SET #MyCursor = CURSOR FOR
SELECT codeMaint from affectationmc where iduser=29;
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #MyField
WHILE ##FETCH_STATUS = 0
BEGIN
delete from mcorr where codemaint=#MyField ;
FETCH NEXT FROM #MyCursor
INTO #MyField
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;

here is the template I use for cursors. It just taking the items from the select and maps them into the variables declared up top and executes your statement. Once it processes the statement in the section --Actions to Loop Here, it changes the variables by selecting the next row from your select statement. This repeats until it process all of the rows in the select.
DECLARE
#variable_A AS varchar(15)
,#variable_B AS INT
,#variable_C AS INT
,#variable_D AS VARCHAR(255)
DECLARE Process_Name CURSOR LOCAL FAST_FORWARD FOR
SELECT
T.Col_A,T.Col_B,T.Col_C,T.Col_D
FROM
tab.my_table AS T;
OPEN Process_Name
FETCH NEXT FROM Process_Name INTO #variable_A,#variable_B,#variable_C,#variable_D
WHILE ##FETCH_STATUS = 0
BEGIN
--Actions to Loop Here
FETCH NEXT FROM Process_Name INTO #variable_A,#variable_B,#variable_C,#variable_D
END
CLOSE Process_Name
DEALLOCATE Process_Name

You're attempting to declare your cursor in one statement, then associate the query with it in a second statement. While some databases will allow this, I'm fairly sure MySQL isn't one of them. Also, MySQL is quite strict about not declaring cursors until after all variables have been declared.
Here's how I would do it:
BEGIN -- note all declarations are inside the BEGIN/END
DECLARE done INT DEFAULT FALSE; -- Good practice is to avoid global variables whenever possible
DECLARE MyField varchar(255); -- varchar2 is Oracle, not MySQL
DECLARE MyCursor CURSOR FOR
SELECT codeMaint
FROM affectationmc
WHERE iduser = 29;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET done = TRUE; -- this will detect end-of-result-set
OPEN MyCursor;
read_loop: LOOP
FETCH NEXT
FROM MyCursor
INTO MyField;
IF done THEN
LEAVE read_loop;
END IF;
DELETE FROM mcorr
WHERE codemaint = MyField ;
END LOOP;
CLOSE MyCursor;
END;

Related

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;

I dont't understand why im getting syntax error on my code below. Can anyone help me?

DELIMITER ##
create trigger tra_Price after update on assets_cdn_charge for each row
begin
declare res int;
declare ids int;
declare idq int;
declare idt int;
set res = (select price from assets_cdn_charge where price = new.price);
set ids = (select id from assets_cdn_charge where price = new.price);
DECLARE cur CURSOR FOR SELECT id FROM assets_cdn_composite WHERE cdn_charge_id = ids;
open cur;
ins_loop:LOOP
fetch cur into idq;
declare curs cursor for select id from assets_cdn_traffic where domain_name_id = idq;
open curs;
ins1_loop:LOOP
fetch curs into idt;
update assets_cdn_traffic set cost = traffic * res where domain_namd_id = idt;
end LOOP;
close curs;
end LOOP;
close cur;
END; ##
when I run this code,I had get this error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'DECLARE cur CURSOR FOR SELECT id FROM
assets_cdn_composite WHERE cdn_charge_id =' at line 9
Probably because:
DECLARE is permitted only inside a BEGIN ... END compound statement
and must be at its start, before any other statements.
...so that line should likely be moved before the two set statements above that point.
I believe that you're going to have other trouble if that fixes that error, because I don't know what you expect that query to retrieve as idq is declared before that point, but is not set to any value?
=====
UPDATE:
Below is an example from a previous comment about the possibility to eliminate cursors altogether. Try this:
BEGIN
UPDATE assets_cdn_traffic
JOIN assets_cdn_composite ON assets_cdn_traffic.domain_name_id = assets_cdn_composite.cdn_charge_id
JOIN assets_cdn_charge ON assets_cdn_charge.id = assets_cdn_composite.cdn_charge_id
SET cost = traffic * NEW.price
WHERE assets_cdn_charge.id = NEW.id
END
However, I would try the update query separately before using in the trigger to make sure that it works as expected. Replace the NEW.price and the NEW.id with test values to verify the handling.

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: Solve my MySQL Cursor Error:1064

DROP TRIGGER IF EXISTS `ACTUALIZAR_LOTE_DETALLE`;
DELIMITER //
CREATE TRIGGER `ACTUALIZAR_LOTE_DETALLE` AFTER INSERT ON `detalle_envio`
FOR EACH ROW BEGIN
DECLARE ID_INVENTARIO_IN INT;
DECLARE ID_LOTE_DETALLE_MIN INT;
DECLARE CANTIDAD_A_COMPARAR INT;
DECLARE CANTIDAD_A_RESTAR INT;
SET CANTIDAD_A_RESTAR = new.cantidad_enviado;
SET ID_INVENTARIO_IN = (Select id_inventario from detalle_requisicion WHERE id_detalle_requisicion = new.id_detalle_requisicion);
DECLARE cur_id CURSOR FOR SELECT id_lote_detalle from lote_detalle WHERE id_inventario = ID_INVENTARIO_IN AND cantidad > 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET DONE = 1;
OPEN cur_id;
read_loop: LOOP
FETCH cur_id INTO LOTE_DETALLE_IDS;
SET CANTIDAD_A_COMPARAR = select cantidad from lote_detalle where id_lote_detalle = LOTE_DETALLE_IDS;
IF CANTIDAD_A_RESTAR > CANTIDAD_A_COMPARAR THEN
UPDATE `lote_detalle` SET cantidad=cantidad-CANTIDAD_A_COMPARAR WHERE id_lote_detalle = LOTE_DETALLE_IDS;
SET CANTIDAD_A_RESTAR = CANTIDAD_A_RESTAR - CANTIDAD_A_COMPARAR;
ELSE
UPDATE `lote_detalle` SET cantidad=cantidad-CANTIDAD_A_RESTAR WHERE id_lote_detalle = LOTE_DETALLE_IDS;
LEAVE read_loop;
END IF;
IF DONE = 1 THEN
LEAVE read_loop;
END IF;
END LOOP read_loop;
CLOSE cur_id;
END
//
DELIMITER ;
Is anything in the cursor?
the query or something?
Is anything in the Syntax?
Cause i have based this Trigger from the syntax of the MySQL Forums
This is the Error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE cur_id CURSOR FOR SELECT id_lote_detalle from lote_detalle WHERE id_inve' at line 9
There are at least following issues with your code:
All declarations should come before any statements (SET in your case). That's what is causing your immediate error.
You didn't declare DONE variable
You didn't declare LOTE_DETALLE_IDS variable, but you declared ID_LOTE_DETALLE_MIN which you didn't use. Perhaps you should rename ID_LOTE_DETALLE_MIN to LOTE_DETALLE_IDS then.
Since declarations go first you have to re-write your cursor definition (e.g. with subquery) because ID_INVENTARIO_IN variable isn't initialized yet
Your whole declaration section can be re-written in a following manner
-- declaration of variables of the same type can be combined
DECLARE ID_INVENTARIO_IN,
LOTE_DETALLE_IDS,
CANTIDAD_A_COMPARARINT,
CANTIDAD_A_RESTAR,
DONE INT;
DECLARE cur_id CURSOR FOR ...
DECLARE CONTINUE HANDLER ...
-- initialize variables
SET ...
Now, I believe your trigger most likely can be re-written with just update statement(s). You can get help with it if you explain in plain words what you're trying to achieve and provide exact table schemas and sample data.

syntax error on DECLARE CURSOR FOR

I dont't understand why im getting syntax error on my sp code below. Can anyone help me figure this out?
SQL Error (1064):
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'DECLARE CUR1 CURSOR FOR SELECT pc.prospectus_courses_id FROM
prereq_cou' at line 8
DELIMITER $$
DROP PROCEDURE IF EXISTS get_prereqs3$$
CREATE PROCEDURE get_prereqs3(IN prosp_courses_id SMALLINT(5))
BEGIN
DECLARE done int DEFAULT FALSE;
DECLARE required SMALLINT(5) default 0;
DECLARE to_search SMALLINT(5) default 0;
DROP TABLE IF EXISTS tmp_list;
CREATE TABLE tmp_list(courses_id SMALLINT(5), courses_id_req SMALLINT(5)) ENGINE = MEMORY;
DECLARE CUR1 CURSOR FOR SELECT pc.prospectus_courses_id
FROM prereq_courses pc
JOIN prerequisites pr on (pr.id = pc.prerequisites_id)
JOIN prospectus_courses ps on (ps.id = pr.prospectus_courses_id)
WHERE ps.id = to_search
MAIN_LOOP: LOOP
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
FETCH cur1 INTO required;
IF done THEN
CLOSE cur1;
LEAVE main_loop;
ELSE
insert into tmp_list values (to_search, required);
set to_search = required;
iterate main_loop;
END IF;
END LOOP;
select c.course_code
from tmp_list t
join prospectus_courses pc on pc.id = t.courses_id_req
join courses c on c.id = pc.courses_id ;
drop table tmp_list;
END$$
DELIMITER ;
Declarations have to be right after a BEGIN block.
In your case just move the DECLARE cur1 CURSOR and DECLARE CONTINUE HANDLER.. two lines up.
Sometimes you want to declare a variable or cursor later in the code, for example only, if a condition is met.
In this case you can wrap the block with a nested BEGIN .. END again.
http://dev.mysql.com/doc/refman/5.5/en/begin-end.html and
http://dev.mysql.com/doc/refman/5.5/en/declare.html
DECLARE is permitted only inside a BEGIN ... END compound statement and must be at its start, before any other statements.
Also you are declaring CUR1 but using cur1.
Is there no need semicolon?
WHERE ps.id = to_search;
^___________