I have a stored procedure in mysql. In it i am selecting some values from database using following statement ,
select version_id from version where version_name between '1.1' and '1.5'
Now i want to run a loop for all selected values from above statement means suppose above statement returns following row ,
version_id (1,5,3,7) so i want to run a loop for values 1,5,3,7 .
How can i achieve this ?
In MySQL, you need to use Cursor element to loop in values
CREATE PROCEDURE CURSOR_LOOP()
BEGIN
DECLARE C1 CURSOR FOR
select version_id where version_name between '1.1' and '1.5'
OPEN C1;
read_loop: LOOP
FETCH C1 INTO v_ID;
IF done THEN
LEAVE read_loop;
END IF;
-- YOUR ACTION HERE
END LOOP;
CLOSE C1;
-- OTHERS ACTIONS
END;
Related
I'm new to Mysql Stored Procedures.
Tring to return rows in a stored procedure after a LOOP.
Here's my code
BEGIN
DECLARE date_SD date;
DECLARE c_stack CURSOR FOR
select SD from t4 where date(SD) >= "2022-05-01" and date(SD)<= "2022-05-30" group by SD;
DROP TEMPORARY TABLE IF EXISTS final_result;
CREATE TEMPORARY TABLE final_result LIKE templaedb.temp_table;
OPEN c_stack;
read_loop: LOOP
FETCH c_stack INTO date_SD;
INSERT INTO final_result VALUES ('first','140','2022-05-06','','1','2','3','4','5');
INSERT INTO final_result VALUES ('last','500','2022-05-06','','11','12','13','14','15');
END LOOP read_loop;
CLOSE c_stack;
select 'Print Test';
select * from final_result;
END
Select statement at last of the Stored Procedure is not working.
Try this
DECLARE date_SD date;
DECLARE c_stack CURSOR FOR
select SD from t4 where date(SD) >= "2022-05-01" and date(SD)<= "2022-05-30" group by SD;
/* add this*/ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TEMPORARY TABLE IF EXISTS final_result;
CREATE TEMPORARY TABLE final_result LIKE templaedb.temp_table;
OPEN c_stack;
read_loop: LOOP
FETCH c_stack INTO date_SD;
/* must include*/
IF done = 1 THEN
LEAVE read_loop;
END IF;
/* must include*/
INSERT INTO final_result VALUES ('first','140','2022-05-06','','1','2','3','4','5');
INSERT INTO final_result VALUES ('last','500','2022-05-06','','11','12','13','14','15');
END LOOP read_loop;
CLOSE c_stack;
select * from final_result;
I have within a database several tables where they all have username column. I would like to update one username and naturally I should update it in all tables.
I have this working solution:
UPDATE `user`,
`user_images`,
`user_comments`
SET `user`.`username` = 'new_name',
`user_images`.`username` = 'new_name',
`user_comments`.`username` = 'new_name'
WHERE `user`.`username` = 'old_name'
AND `user_images`.`username` = 'old_name'
AND `user_comments`.`username` = 'old_name'
I am hoping for a better query that can do the same action, as if table numbers got increased, do I really need to do this in 100 lines?
It sounds painful if you have to update each table. I would suggest using a stored procedure to finish the tedious job. Fisrt of all , make a table(named tablelist) which list all the tablename you would like to update. Then call the procedure by providing the two parameters where the o_name is the name you would like to change and the n_name is the new name to be changed into.
delimiter //
drop procedure if exists update_name//
create procedure update_name (o_name varchar(30),n_name varchar(30))
begin
declare t_name varchar(30);
declare done bool default false;
declare csr cursor for select tablename from tablelist;
declare continue handler for not found set done=true;
open csr;
lp: loop
fetch csr into t_name;
if done=true then
leave lp;
end if;
set #prep=concat('update ',t_name,' set `username`= "',n_name,'" where `username`= "',o_name,'";');
prepare prep_stat from #prep;
execute prep_stat;
deallocate prepare prep_stat;
end loop lp;
close csr;
end//
delimiter ;
The following call will change the name from john(case insensitive) to Xero in all tables listed in the tablelist table.
call update_name('John','Xero');
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
I am new to stored procedure in PostgreSQL (pgSQL) .I need some one help to crack my problem .I am doing the migration process from oracle to PostgreSQL for that I have used some stored procedure concept. I have tried in SQL stored procedure its working in SQL, but same code i have trying to convert into pgSQL. I have faced a issue in line by line .can any one help me to convert same code SQL into PostgreSQL. i have attached my SQL procedure code below. can any one suggest me aright way to process the code.
code:
delimiter;
drop procedure if exists patient_form_values;
delimiter $$
create procedure patient_form_values()
begin
declare columnName varchar(200) ;
declare done tinyint default 0;
declare cur1 cursor for select distinct COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'CASESHEETCOMPLAINTS' and table_schema='hms_empty_copy';
declare continue handler for not found set done = 1;
open cur1;
read_loop : loop
fetch from cur1 into columnName;
if done then leave read_loop;
end if;
set #insertValues := concat('INSERT INTO patient_form_temp(patient_id, form_template_id, creator_id, created_date)
SELECT c.patient_id as patient_id, 41 AS form_template_id, 2 AS creator_id, c.created_date AS created_date
FROM CASESHEETCOMPLAINTS c
WHERE c.', columnName,' IS NOT NULL GROUP BY c.patient_id, c.created_date');
select #insertValues;
prepare stmt from #insertValues;
execute stmt;
end loop;
close cur1;
end $$
delimiter ;
call patient_form_values();
drop procedure if exists patient_form_values;
--To delete the empty records.
DELETE FROM patient_form WHERE id NOT IN(SELECT patient_form_id FROM patient_form_value);
insert into patient_form(patient_id, form_template_id, creator_id, created_date)select patient_id, form_template_id, creator_id, created_date from patient_form_temp GROUP BY patient_id, created_date
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.