I did a mysql procedure that insert in a table a number of rows for each row of other table. Thats the code:
PROCEDURE `name` (`var1` SMALLINT(6), `var2` SMALLINT(6)) BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE a SMALLINT(6);
DECLARE cur CURSOR FOR SELECT id FROM tableA WHERE fk_id = var2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
IF done THEN
LEAVE read_loop;
END IF;
FETCH cur INTO a;
INSERT INTO tableB VALUES(var1, a);
END LOOP;
CLOSE cur;
My problem is that the last row is inserted two times. How can I resolve this?
Thanks
Related
I have a stored procedure snippet like this
CREATE DEFINER=`root`#`%` PROCEDURE `new_procedure`()
BEGIN
DECLARE c_id varchar(100) DEFAULT "";
DECLARE cursor1 CURSOR for select id from t1 where name like 's%';
OPEN cursor1;
get_t1: LOOP
FETCH cursor1 into c_id;
p:begin
declare cursor2 cursor for select id from t2 where cl_id=c_id;
open cursor2;
get_t2: loop
fetch project_cursor into p_id;
// perform some tasks
t:begin
declare cursor3 cursor for select id from t3 where pr_id=p_id;
open cursor3;
get_t3:loop
fetch cursor3 into t_id;
IF v_finished = 1 THEN
LEAVE get_t3;
END IF;
//perform some tasks
close cursor3;
select p_id;
end t;
end loop t2;
end p;
END LOOP t1;
END
here select statement is not displaying any data
when i write select under cursor 3 it is working.
did i made any mistake? anything I missed
Some basic logic has been added in your SP, Try it whether this is what you are expecting.
CREATE DEFINER=`root`#`%` PROCEDURE `new_procedure`()
BEGIN
DECLARE c_id VARCHAR(100) DEFAULT "";
DECLARE done1 BOOLEAN DEFAULT FALSE;
DECLARE cursor1 CURSOR FOR SELECT id FROM t1 WHERE name LIKE 's%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1=TRUE;
OPEN cursor1;
GET_T1: LOOP
FETCH cursor1 INTO c_id;
IF done1 THEN
LEAVE GET_T1;
END IF;
P:BEGIN
DECLARE p_id INT ; -- check which data types suits you, might be int
DECLARE done2 BOOLEAN DEFAULT FALSE;
DECLARE cursor2 CURSOR FOR SELECT id FROM t2 WHERE cl_id=c_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2=TRUE;
OPEN cursor2;
GET_T2: LOOP
FETCH cursor2 INTO p_id;
IF done2 THEN
LEAVE GET_T2;
END IF;
/* perform some task */
T:BEGIN
DECLARE t_id INT ; -- check which data types suits you, might be int
DECLARE done3 BOOLEAN DEFAULT FALSE;
DECLARE cursor3 CURSOR FOR SELECT id FROM t3 WHERE pr_id=p_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done3=TRUE;
OPEN cursor3;
GET_T3:LOOP
FETCH cursor3 INTO t_id;
IF done3 THEN
LEAVE GET_T3;
END IF;
/* perform some tasks */
#select p_id; -- don't know what you are doing with this
END LOOP GET_T3;
CLOSE cursor3;
SET done3=FALSE;
END T;
END LOOP GET_T2;
CLOSE cursor2;
SET done2= FALSE;
END P;
END LOOP GET_T1;
CLOSE cursor1;
SET done1= FALSE;
END
Running this routine on HeidiSQL and it runs with 0 rows affected, even though there should be exactly 1 row affected. both select statements seem to work fine outside this Stored Procedure.
BEGIN
DECLARE someId INT;
DECLARE done INT DEFAULT FALSE;
DECLARE cur1 CURSOR FOR
select anotherId from tableA
where yetAnotherId IN(another select statement);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
IF done THEN
LEAVE read_loop;
END IF;
FETCH cur1 INTO someId;
update tableB
set x = 'hello', y = 'world'
where something = someId;
END LOOP;
CLOSE cur1;
END;
I would like to get an idea what could be wrong with the structure of this routine. It looks to me that even thoughthe cursor should contain 1 entry, It does not.
Thanks
EDIT: It looks like 'someId' was matching a table field with the same name, thus the issue. This has been resolved now.
Your SP looks good, I have made changes for MySql please try it
BEGIN
DECLARE someId INT;
DECLARE done INT DEFAULT FALSE;
DECLARE cur1 CURSOR FOR
select anotherId from tableA
where yetAnotherId IN(another select statement);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO someId;
update tableB
set x = 'hello', y = 'world'
where something = someId;
IF done THEN
CLOSE cur1;
LEAVE read_loop;
END IF;
END LOOP read_loop;
END;
I am facing issue of passing dynamic table name in trigger in MySQL.
Here is my
DELIMITER $$
DROP TRIGGER `demo_database`.`my_trigger`$$
create trigger `demo_database`.`my_trigger` AFTER INSERT on `demo_database`.`tablename`
for each row BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE a varchar(255);
DECLARE cur1 CURSOR FOR SELECT TABLE_NAME FROM information_schema.tables WHERE table_name LIKE '%_pbxware_minilcr' limit 1,10000000000;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO a;
IF done THEN
LEAVE read_loop;
END IF;
INSERT INTO a (`server`,`tbd`,`lcr`,`route`,`destination`,`trunk`,`ext`) values (3,NULL,'primary','11','1','78',NULL);
END LOOP;
CLOSE cur1;
END;
$$
DELIMITER ;
Here in above cur1 Cursor, I am fetching tables name and I want to insert value in that (fetched) tables..
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
This is what i tried. I couldnt get my values inserted into table. can anyone help me out ..
DELIMITER $$
USE `SampleDB`$$
DROP PROCEDURE IF EXISTS `Sample`$$
CREATE PROCEDURE `SampleDB`.`Sample`()
BEGIN
#declare variable
DECLARE tenantName VARCHAR(255);
DECLARE tenantAddress VARCHAR(255);
DECLARE done INT DEFAULT FALSE;
DECLARE cur1 CURSOR FOR SELECT tenant_name,tenant_address FROM tenant;
#open cursor
OPEN cur1;
#starts the loop
the_loop: LOOP
#get the values of each column into our variables
FETCH cur1 INTO tenantName,tenantAddress;
IF done THEN
LEAVE the_loop;
END IF;
#Insert it
INSERT INTO tenant(tenant_name,tenant_address)
VALUES (tenantName,tenantAddress);
END LOOP the_loop;
CLOSE cur1;
END$$
DELIMITER ;
Indeed lack 13.6.7.2. DECLARE ... HANDLER Syntax:
...
DECLARE cur1 CURSOR FOR SELECT tenant_name, tenant_address FROM tenant;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE;
#open cursor
...
But do you really need a cursor? With a statement like this, you can avoid the cursor:
INSERT INTO `tenant` (`tenant_name`, `tenant_address`)
SELECT `tenant_name`, `tenant_address` FROM `tenant`;