MySql Stored Procedure Loop Cursor - Syntax error - mysql

Where is the syntax error?
DECLARE irid INT DEFAULT 0;
DECLARE tmp_joinid INT DEFAULT 0;
DECLARE loopjoins_eof INT DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET loopjoins_eof = TRUE;
START TRANSACTION;
SET irid = (SELECT id FROM `tables` WHERE `adapter_id`=_aid AND `view_id`=_vid AND `name`=_tname);
IF irid IS NOT NULL THEN
DECLARE cur0 CURSOR FOR SELECT `joins`.`id` FROM `joins` WHERE `table_left_id`=irid OR `table_right_id`=irid;
OPEN cur0;
loopjoins: LOOP
FETCH cur0 INTO tmp_joinid;
IF loopjoins_eof THEN
LEAVE loopjoins;
END IF;
-- Lösche Join-Columns
DELETE FROM `join_columns` WHERE `join_id`=tmp_joinid;
END LOOP loopjoins;
CLOSE cur0;
END IF;
COMMIT;
SELECT irid;
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 cur0 CURSOR FOR SELECT joins.id FROM joins WHERE table_left_id=i' at line 12
Thank you

a much better option is to avoid the cursor, you can replace the cursor with something like
DELETE FROM `join_columns`
WHERE `join_id` in
(SELECT `id`
FROM `joins`
WHERE `table_left_id`=irid OR `table_right_id`=irid);

From the manual:
Cursor declarations must appear before handler declarations and after variable and condition declarations.

Related

Getting Syntax Error in MySQL Stored Procedure while trying nested Cursors

I have a MySQL Stored Procedure Script in which I am trying to implement a nested cursors . Following is my code
DELIMITER //
DROP PROCEDURE IF EXISTS PopulateStaleEntityTable//
DELETE FROM bucket_stale;
LOAD DATA LOCAL INFILE '/home/centos/mysql1.txt' INTO TABLE bucket_stale;
CREATE PROCEDURE PopulateStaleEntityTable()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE finished_stale INTEGER DEFAULT 0;
DECLARE product_offer_id_var bigint(20) DEFAULT 0;
DECLARE product_offer_group_id_var bigint(20) DEFAULT 0;
DECLARE batch_count INTEGER DEFAULT 0;
DECLARE max_batch_count INTEGER DEFAULT 100;
DECLARE bucket_id_var bigint(10) DEFAULT 0;
DECLARE stale_cursor CURSOR FOR
SELECT staleid FROM bucket_stale;
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished_stale = 1;
OPEN stale_cursor;
insert_stale : LOOP
FETCH stale_cursor INTO bucket_id_var;
SELECT bucket_id_var;
BEGIN
DECLARE product_cursor CURSOR FOR
SELECT product_offer_id FROM product where bucket_id='1086';
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
OPEN product_cursor;
insert_entity: LOOP
START TRANSACTION;
FETCH product_cursor INTO product_offer_id_var;
SELECT product_offer_group_id INTO product_offer_group_id_var FROM product_offer where id=product_offer_id_var;
INSERT IGNORE INTO stale_cached_entity (entity_type,entity_id,cache_action,created,field_change) VALUES ('PRODUCT_OFFER_GROUP',product_offer_group_id_var, 'UPDATE',now(),'DEFAULT_SUPC_LIST1');
SET batch_count=batch_count+1;
IF batch_count > max_batch_count THEN
COMMIT;
SET batch_count=0;
END IF;
IF finished = 1 THEN
LEAVE insert_entity;
END IF;
END LOOP insert_entity
END;
IF finished_stale = 1 THEN
LEAVE insert_stale;
END IF;
END LOOP insert_stale;
CLOSE stale_cursor;
END//
DELIMITER ;
When i try and run this script it gives the following error
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 'END;
IF finished_stale = 1 THEN
LEAVE insert_stale;
END IF; ' at line 38
I tried to figure out whats wrong but i couldn't . What am I missing ?
The problem lies in this line:
END LOOP insert_entity
If you review the example of cursor code at https://dev.mysql.com/doc/refman/5.7/en/cursors.html you see that END LOOP does not need the label, and it needs a semicolon statement terminator.
Like this:
END LOOP;
I agree with #tadman's comment. I understand some developers who have had experience with Oracle or Microsoft have an expectation of using stored procedures, but frankly, MySQL's stored procedure support sucks so bad you will be happier and more productive writing some simple Python scripts (or any other language).

MariaDB Error creating Function when it worked on MySQL

Please consider the following function defination. I created and set it up on MySQL 5.1 but it's failing in MariaDB 5.5
CREATE DEFINER=`root`#`127.0.0.1` FUNCTION `weighted_mean_by_kpi`(`KPIID` INT, `employee_id` INT, `date` DATE)
RETURNS decimal(6,3)
LANGUAGE SQL
DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE rating_number INT DEFAULT 0;
DECLARE rating_count INT DEFAULT 0;
DECLARE rating_total INT DEFAULT 0;
DECLARE weighted_total DOUBLE DEFAULT 0;
DECLARE cur CURSOR FOR
SELECT COUNT(rating), rating FROM employees_KPIs WHERE kpi_id = KPIID AND employee_id = employee_id AND employees_KPIs.created_at LIKE CONCAT("%",DATE_FORMAT(date,'%Y-%m'),"%") GROUP BY rating;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
RATING: LOOP
FETCH cur INTO rating_count, rating_number;
IF done = 1 THEN
LEAVE RATING;
END IF;
SET weighted_total = weighted_total + (rating_number * rating_count);
SET rating_total = rating_total + rating_count;
END LOOP RATING;
return (weighted_total/rating_total);
#return (weighted_total);
CLOSE cur;
END
I get the following error:
ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 8
Thanks
Mysql sees the ';' delimiters in the function and breaks your CREATE FUNCTION statement.
To avoid this, change the delimiter before you define the function, and then change it back afterward:
Like:
DELIMITER //
-- your create function definition statement here
//
DELIMITER ;
As in your code the first ; semicolon was found at line 8, it tried to execute it the code up to the ';', and the syntax was invalid because it was incomplete (BEGIN without 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;
^___________

can't create mysql stored procedure

I'm a bit of a noob when it comes to stored procedures in general, but I'm trying to write the following
Create procedure clone_perms
as
declare #new_id varchar(30), #old_id varchar(30)
declare get_perms cursor for select userspermsUserid, userspermsPermission from users_permissions where userspermsUserid=#old_id
declare #perms varchar(30), #on_off boolean
FETCH get_perms into #perms, #on_off
while(##sqlstatus=0)
BEGIN
if exists ( select 1 from permissions where userspermsUserid=#new_id and userspermsPermID=#perm )
BEGIN
update permissions set userspermsPermission=#on_off where userspermsUserid=#new_id and userspermsPermID=#perm
END
else
BEGIN
insert permissions (userspermsUserID, userspermsPermID, userspermsPermission) values (#new_id, #perms, #on_off)
END
FETCH get_perms into #perms, #on_off
END
CLOSE get_perms
DEALLOCATE CURSOR get_perms
end
. I get the following error when trying to create it:
/* 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 'as declare #new_id varchar(30) declare #old_id varchar(30) declare get_perm' at line 2 */
. Does anyone know what I need to do to make this work?
You need to have BEGIN tag after CREATE PROCEDURE clone_perms and not AS
don't use an # to start local (declared) variable names, that's only for user variables you create with the
SET #varname=value;
statement. you'll also need to terminate your statements with a semicolon. that's the cause of the latest error, there's no ; after your first declare statement.