How to make a while in a stored procedure with phpmyadmin, error #1064 - mysql

I try to create a stored procedure in phpmyadmin, but I get a error 1064 on line 12 (where the WHILE is). This is the first time I try to create a stored procedure.
BEGIN
DECLARE product_id INT;
DECLARE product_min_age nvarchar(500);
DECLARE cur CURSOR for
SELECT product_min_age, product_id FROM _vm_product;
open cur;
fetch next from cur into product_min_age, product_id;
while FETCH_STATUS = 0 BEGIN
INSERT INTO _virtuemart_product_customfields (virtuemart_product_id, virtuemart_custom_id, customfield_value, customfield_params) VALUES
( product_id, 5, product_min_age, 'addEmpty=0|selectType=0|');
fetch next from cur into product_min_age,product_id;
END;
close cur;
END
Thank you

You should change that to below. See Documentation for more information.
open cur;
read_loop: LOOP
fetch cur into product_min_age, product_id;
INSERT INTO _virtuemart_product_customfields (virtuemart_product_id, virtuemart_custom_id, customfield_value, customfield_params) VALUES
( product_id, 5, product_min_age, 'addEmpty=0|selectType=0|');
END LOOP;
close cur;

The accepted answer is indeed correct and so is your own answer. Unfortunately the approach is completely wrong!
One does not generally perform sql queries inside a loop unless as a last resort. Select / loop / insert is in fact a frequent pattern followed by people writing their first stored procedure. but there is a better way, a much much better way. And that is INSERT .. SELECT
With INSERT ... SELECT, you can quickly insert many rows into a table
from one or many tables. For example:
Your complex stored procedure reduces to:
INSERT INTO _virtuemart_product_customfields (virtuemart_product_id, virtuemart_custom_id, customfield_value, customfield_params)
SELECT product_id, 5, product_min_age, 'addEmpty=0|selectType=0|'
FROM _vm_product
That's it, just a simple select, no stored procedures!
A second issue is that you are stored delimited text in a column.
addEmpty=0|selectType=0|
I am not quite sure why you are doing this but it's most unusual.

If someone want to see my final result:
BEGIN
DECLARE _product_id INT;
DECLARE _product_min_age nvarchar(500);
DECLARE done INT DEFAULT 0;
DECLARE cur CURSOR for SELECT product_min_age, product_id FROM _vm_product;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
open cur;
read_loop: LOOP
fetch cur into _product_min_age, _product_id;
IF done = 1 THEN
LEAVE read_loop;
END IF;
INSERT INTO _virtuemart_product_customfields (virtuemart_product_id, virtuemart_custom_id, customfield_value, customfield_params) VALUES
( _product_id, 5, _product_min_age, 'addEmpty=0|selectType=0|');
END LOOP;
close cur;
END

Related

Nested Cursor Into Mysql

I am creating cursor within cursor and first cursor getting unique value and second cursor is generating details number of rows. I found second cursor is running one time and not populating rows against every row id. Please guide
DELIMITER $$
USE `dum_data`$$
DROP PROCEDURE IF EXISTS `sp_process_gen`$$
CREATE DEFINER=`test`#`%` PROCEDURE `sp_process_gen`()
BEGIN
DECLARE cur1_done,cur2_done INT DEFAULT 0;
DECLARE v_thread_id, v_id,v_tab,v_event_time INT;
DECLARE v_stime,v_etime DATETIME;
-- declaring cursor
DECLARE cur1 CURSOR FOR
SELECT thread_id
FROM general_log
-- WHERE thread_id in (306710429,306711335)
GROUP BY thread_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET cur1_done = 1;
OPEN cur1;
cur1_loop: LOOP
FETCH cur1 INTO v_thread_id;
-- INSERT INTO aa VALUES(NULL,v_thread_id,NULL,NULL);
block2: BEGIN
DECLARE cur2 CURSOR FOR
SELECT id , event_time
FROM general_log
WHERE thread_id = v_thread_id
ORDER BY id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET cur2_done = 1;
OPEN cur2;
cur2_loop: LOOP
FETCH cur2 INTO v_id,v_stime;
IF cur2_done THEN
-- set cur1_done = 0;
CLOSE cur2;
LEAVE cur2_loop;
END IF;
-- INSERT INTO aa VALUES(v_id,v_thread_id,v_stime,v_stime);
INSERT INTO aa(thread_id) VALUES(v_thread_id);
-- FETCH cur2 INTO v_id,v_stime;
END LOOP cur2_loop;
END block2;
IF cur1_done THEN
CLOSE cur1;
LEAVE cur1_loop;
END IF;
INSERT INTO aa(thread_id) VALUES(999999);
-- FETCH cur1 INTO v_thread_id;
END LOOP cur1_loop;
-- CLOSE cur;
END$$
DELIMITER ;
I suspect your problem is the two CONTINUE HANDLER FOR NOT FOUND structures.
The second cursor will get it's first NOT FOUND at the end its loop, trigger both handlers... causing both loops to exit.
The way around this is to have a second stored procedure that contains the inner loop, and call that procedure from the outer loop. That way your handlers are in separate contexts.

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;

MySQL cursor not exit in stored procedure

Hell sir,
I have used cursor for fetching data from one my table. After fetching data from cursor , I insert data another table. Problem is that it continue inserting data not exit.That means it is continue inserting.....
Here is my code used in stored procedure.
DECLARE done INTEGER DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT customercode,productid
FROM dt_products;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN cur1;
LOOPROWS:
LOOP
FETCH cur1 INTO v_customer_id, v_productid;
IF done = 1
THEN
LEAVE LOOPROWS;
END IF;
INSERT INTO orders(ORDER_ID, mailid)
VALUES (v_customer_id, v_productid);
END LOOP LOOPROWS;
CLOSE cur1
Please help me...

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

Declare variable MySQL trigger

My question might be simple for you, if you're used to MySQL. I'm used to PostgreSQL SGBD and I'm trying to translate a PL/PgSQL script to MySQL.
Here is what I have :
delimiter //
CREATE TRIGGER pgl_new_user
AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE m_user_team_id integer;
SELECT id INTO m_user_team_id FROM user_teams WHERE name = "pgl_reporters";
DECLARE m_projects_id integer;
DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = m_user_team_id;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO m_projects_id;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access)
VALUES (NEW.id, m_projects_id, now(), now(), 20);
END LOOP;
CLOSE cur;
END//
But MySQL Workbench gives me an error on DECLARE m_projects_id. I don't really understand because I've the same instruction two lines above...
Any hints ?
EDIT: neubert solved this error. Thanks.
But yet, when I try to insert into users :
Error Code: 1329. No data - zero rows fetched, selected, or processed
Do you have any idea ? Or better, do you know how I can get a better error message ?
All DECLAREs need to be at the top. ie.
delimiter //
CREATE TRIGGER pgl_new_user
AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE m_user_team_id integer;
DECLARE m_projects_id integer;
DECLARE cur CURSOR FOR SELECT project_id FROM user_team_project_relationships WHERE user_team_id = m_user_team_id;
SET #m_user_team_id := (SELECT id FROM user_teams WHERE name = "pgl_reporters");
OPEN cur;
ins_loop: LOOP
FETCH cur INTO m_projects_id;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT INTO users_projects (user_id, project_id, created_at, updated_at, project_access)
VALUES (NEW.id, m_projects_id, now(), now(), 20);
END LOOP;
CLOSE cur;
END//
Agree with neubert about the DECLARE statements, this will fix syntax error. But I would suggest you to avoid using openning cursors, they may be slow.
For your task: use INSERT...SELECT statement which will help you to copy data from one table to another using only one query.
INSERT ... SELECT Syntax.