Looping mysql query inside trigger - mysql

Here is my trigger:
DELIMITER |
CREATE TRIGGER update_status_penjualan AFTER UPDATE
ON penjualan FOR EACH ROW
BEGIN
DECLARE arrayresult = (SELECT * FROM rincian_penjualan WHERE id_penjualan = OLD.id)
for ids in arrayresults
UPDATE buku SET stok = stok + ids['jumlah']; WHERE noisbn = ids['noisbn'];
endfor
END;
|
DELIMITER ;
I'v got many error, i think because my looping code is not right.
Can anyone tell me how to fix it?
Thanks ~

You could try with a cursor, something like this:
DELIMITER |
CREATE TRIGGER update_status_penjualan AFTER UPDATE
ON penjualan FOR EACH ROW
BEGIN
declare jumlah_c int;
declare noisbn_c int;
declare done int;
declare cur1 cursor for
SELECT * FROM rincian_penjualan WHERE id_penjualan = OLD.id;
declare continue handler for not found set done=1;
set done = 0;
open cur1;
igmLoop: loop
fetch cur1 into jumlah_c,noisbn_c;
if done = 1 then leave igmLoop; end if;
UPDATE buku SET stok = stok + jumlah_c WHERE noisbn = noisbn_c;
end loop igmLoop;
close cur1;
END;
|
DELIMITER ;

Related

mysql table trigger throughs error

Getting error on following trigger:
DELIMITER $$
CREATE TRIGGER limit_refferals AFTER INSERT
ON wpmr_aff_referrals
FOR EACH ROW
BEGIN
DECLARE vCNT INT;
DECLARE USERID varchar(50);
DECLARE AFFILIATEID varchar(50);
DECLARE i INTEGER;
DECLARE curs1 CURSOR FOR SELECT USER_ID,affiliate_id
FROM `wpmr_aff_referrals` WHERE affiliate_id=:NEW.affiliate_id;
SELECT CUSTOMERLEVEL(:NEW.affiliate_id) INTO vCNT;
IF (vCNT>=3)
set i=1;
OPEN curs1;
read_loop: LOOP
FETCH curs1 INTO USERID,AFFILIATEID;
SELECT CUSTOMERLEVEL(:NEW.affiliate_id) INTO vCNT;
IF (vCNT>=3)
set i=i+1;
ELSE
set new.affiliate_id= AFFILIATEID;
END IF;
END LOOP read_loop;
CLOSE curs1;
END IF;
END$$
DELIMITER ;
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 ':NEW.affiliate_id; SELECT CUSTOMERLEVEL(:NEW.affiliate_id) INTO
vCNT;
IF (vC' at line 10
DELIMITER $$
CREATE TRIGGER limit_refferals BEFORE INSERT
ON wpmr_aff_referrals
FOR EACH ROW
BEGIN
DECLARE vCNT INT;
DECLARE USERID varchar(50);
DECLARE AFFILIATEID varchar(50);
DECLARE i INTEGER;
DECLARE curs1 CURSOR FOR
SELECT USER_ID,affiliate_id
FROM `wpmr_aff_referrals` WHERE affiliate_id=NEW.affiliate_id;
SELECT CUSTOMERLEVEL(NEW.affiliate_id) INTO vCNT;
IF (vCNT >=3) THEN /*<------------Made changes at this line*/
set i=1;
OPEN curs1;
read_loop : LOOP
FETCH curs1 INTO USERID,AFFILIATEID;
SELECT CUSTOMERLEVEL(NEW.affiliate_id) INTO vCNT;
IF (vCNT>=3) THEN /*<------------Made changes at this line*/
set i=i+1;
ELSE
set new.affiliate_id= AFFILIATEID;
END IF;
END LOOP read_loop;
CLOSE curs1;
END IF;
END$$
DELIMITER ;
Try above code.
One more thing you can't use NEW row for BEFORE UPDATE TRIGGER.So i had made changes to AFTER UPDATE TRIGGER.
We don't need : for NEW and OLD value,you can directly check that value using NEW.VAL and OLD.VAL.
Also whenever you use IF IN TRIGGER,PROCEDURE and FUNCTION put THEN and then write you logic
Hope this will help you.
Remove the ":" to pass the parameter NEW.affiliate_id to the CUSTOMERLEVEL function like this:
SELECT CUSTOMERLEVEL(NEW.affiliate_id) INTO vCNT

couldnt compile mysql procedure for cursors

I am trying to use the below procedure to update a table but i could not compile the procedure.
CREATE
PROCEDURE `propmanage2016`.`test`()
DECLARE CURSOR cur1 FOR
SELECT unit_id, unit_code FROM t_units WHERE unit_projectid = 1;
DECLARE done INT DEFAULT FALSE;
DECLARE a INT;
DECLARE b VARCHAR(200);
DECLARE done INT DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
BEGIN
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO b , a ;
IF done THEN
LEAVE read_loop;
END IF;
UPDATE t_owner_resident SET or_unit = a WHERE unit_name = b;
END LOOP;
CLOSE cur1;
END;
please give some help
Sure you can't do it like this without the stored procedure?
UPDATE t_owner_resident ow INNER JOIN t_units t set ow.unit_name = t.unit_code
WHERE o.unit_name = t.unit_id and t.unit_projectid = 1
Note: I think a,b is mixed up in your SP, so please excuse if i've got the column names slightly mixed up too

Need help customizing mysql trigger

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

Trigger is not working properly

I have create trigger for some condition but its through error.
Here is trigger code.
DELIMITER //
CREATE TRIGGER `getcrm`.`update_round_date` AFTER UPDATE ON `getcrm`.`vtiger_stockcheckcf`
FOR EACH ROW begin
DECLARE retribAn INTEGER DEFAULT 0;
DECLARE curEdate datetime;
DECLARE done INT DEFAULT 0;
DECLARE curTipo CURSOR FOR
SELECT a.*, b.*, c.* FROM vtiger_crmentity AS a, vtiger_stockcheck AS b,vtiger_stockcheckcf AS c WHERE a.crmid = b.stockcheckid AND a.crmid = c.stockcheckid AND c.cf_746 = 'Pending' AND a.setype='StockCheck';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN curTipo;
REPEAT
FETCH curTipo INTO retribAn;
IF NOT done THEN
set curEdate = NOW();
IF a.createdtime = curEdate AND c.cf_746 = Pending THEN
INSERT INTO vtiger_cancellationcf(scheckid,cf_1150,cf_1152,cf_1154,cf_1156,cf_1151,cf_1153,cf_1155,cf_1157,cf_1158,cf_1160,cf_1162,cf_1159,
cf_1161,cf_1163,cf_1203,cf_1178,cf_1180,cf_1182,cf_1184,cf_1186,cf_1178,cf_1180,cf_1182,cf_1184,cf_1186,cf_1179,cf_1181,
cf_1183,cf_1185,cf_1187,cf_1179,cf_1181,cf_1183,cf_1185,cf_1187,cf_1164,cf_1166,cf_1168,cf_1170,cf_1165,cf_1167,cf_1169,
cf_1171,cf_1173,cf_1176,cf_1177,cf_1172,cf_1174,cf_1175,cf_1188,cf_1189,cf_1190) values ('a.crmid','"c.cf_709"','"c.cf_711"','"c.cf_713"','"c.cf_715"','"c.cf_710"','"c.cf_712"','"c.cf_714"',
'"c.cf_716"','"c.cf_717"','"c.cf_719"','"c.cf_721"','"c.cf_718"','"c.cf_720"','"c.cf_844"','"c.cf_1079"','"c.cf_736"',
'"c.cf_738"','"c.cf_740"','"c.cf_742"','"c.cf_744"','"c.cf_737"','"c.cf_739"','"c.cf_741"','"c.cf_743"','"c.cf_745"',
'"c.cf_722"','"c.cf_724"','"c.cf_726"','"c.cf_723"','"c.cf_725"','"c.cf_727"','"c.cf_729"','"c.cf_731"','"c.cf_734"',
'"c.cf_735"','"c.cf_730"','"c.cf_732"','"c.cf_733"','"b.stockcheck"','"c.cf_746"','"c.cf_1080"','"c.cf_1081"');
insert into vtiger_cancellation (cancellationid,cancellation,scheckid) values ('a.crmid',' ','c.cf_709');
insert into vtiger_crmentity (crmid,smcreatorid,smownerid,modifiedby,setype,description,createdtime,modifiedtime,viewedtime,status,version,presence,deleted,label) values ('a.crmid','a.smcreatorid','a.smownerid','a.smcreatorid','Cancellation','','curEdate','curEdate','','','0','1','0','');
delete FROM vtiger_crmentity_seq where id='a.crmid';
insert into vtiger_crmentity_seq (id)values ('a.crmid');
END IF;
END IF;
UNTIL done END REPEAT;
CLOSE curTipo;
end
//
DELIMITER
Here is error when any changes on table.
1328 - Incorrect number of FETCH variables
Thanks for advance
I think the problem is here : FETCH curTipo INTO retribAn; your trying to fetch a complete row into a integer.
You should read more on CURSORS .
EXAMPLE:
DECLARE a CHAR(16);
DECLARE b INT;
DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
OPEN cur1;
FETCH cur1 INTO a, b;

Using for loop in MySql data set

How to use for loop in MySQL data set ?
FOR x IN (SELECT column FROM table_name WHERE column_2 = input_val)
LOOP
sum_total := sum_total + x.column ;
END LOOP;
This is an example how I used to loop data set in oracle.
How can this be achieved in MySql ?
How about not looping at all. It's SQL after all.
SELECT SUM(`column`) total
FROM table_name
WHERE column_2 = <input_val>
Otherwise use CURSOR
Now, equivalent loop using CURSOR will look like
DELIMITER $$
CREATE PROCEDURE sp_loop(IN input_val INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE sum_current, sum_total INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT column1 FROM table_name WHERE column2 = input_val;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO sum_current;
IF done THEN
LEAVE read_loop;
END IF;
SET sum_total = sum_total + sum_current;
END LOOP;
CLOSE cur1;
SELECT sum_total;
END$$
DELIMITER ;
Here is SQLFiddle
DROP PROCEDURE IF EXISTS `foo`.`usp_cursor_example`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `foo`.`usp_cursor_example`(
IN name_in VARCHAR(255)
)
READS SQL DATA
BEGIN
DECLARE name_val VARCHAR(255);
DECLARE status_update_val VARCHAR(255);
-- Declare variables used just for cursor and loop control
DECLARE no_more_rows BOOLEAN;
DECLARE loop_cntr INT DEFAULT 0;
DECLARE num_rows INT DEFAULT 0;
-- Declare the cursor
DECLARE friends_cur CURSOR FOR
SELECT
name
, status_update
FROM foo.friend_status
WHERE name = name_in;
-- Declare 'handlers' for exceptions
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET no_more_rows = TRUE;
OPEN friends_cur;
select FOUND_ROWS() into num_rows;
the_loop: LOOP
FETCH friends_cur
INTO name_val
, status_update_val;
IF no_more_rows THEN
CLOSE friends_cur;
LEAVE the_loop;
END IF;
select name_val, status_update_val;
-- count the number of times looped
SET loop_cntr = loop_cntr + 1;
END LOOP the_loop;
-- 'print' the output so we can see they are the same
select num_rows, loop_cntr;
END
DELIMITER ;