SQL trigger after update update next row - mysql

I have a table that looks something like this:
Columns:
user_id int(11) PK
module_id int(11) PK
academy_team_id int(11) PK
academy_id int(11) PK
sort_number int(11)
is_complete int(11)
score_to_pass int(11)
is_open int(11)
Now i wish to add a trigger so that when you update this table if the value is_complete is equal to 1 then update the next row's is_open and set it to1
I have attempted with the following trigger sql:
begin
if new.is_complete = 1 then
set next.is_open = 1;
end if ;
end
Sadly this did not work so im not sure how to do it can anyone push me in the right direction?
According to pala_ Answer
im getting the following error when updating my row:
ERROR 1442: 1442: Can't update table 'user_has_academy_module' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
SQL Statement:
UPDATE `system`.`user_has_academy_module` SET `is_complete`='1' WHERE `user_id`='1' and`module_id`='11' and`academy_team_id`='49' and`academy_id`='29'

Your basic trigger body should be something like this:
begin
if new.is_complete = 1 and (select id from <table> where user_id = new.user_id and module_id = new.module_id and academy_team_id = new.academy_team_id sort_number = new.sort_number +1 ) then
update <table> set is_open = 1
where user_id = new.user_id
and academy_team_id = new.academy_team_id
and module_id = new.module_id
and sort_number = new.sort_number + 1;
end if
end
It will check to see if there IS another thing to set open (based on same user_id, academy_team_id and module_id, and next sequential sort_number), and if there is, set it open.
MySQL cant update the same table the trigger is set on. It will need to be done with a stored procedure instead.
delimiter //
create procedure completeandopen(IN param INT)
begin
declare next_id integer;
declare _user_id integer;
declare _module_id integer;
declare _academy_team_id integer;
declare _sort_number integer;
select user_id,
module_id,
academy_team_id,
sort_number
into _user_id,
_module_id,
_academy_team_id,
_sort_number
from tester
where id = param;
update tester set is_complete = 1 where id = param;
select id
into next_id
from tester
where id = param + 1
and user_id = _user_id
and module_id = _module_id
and academy_team_id = _academy_team_id
and sort_number = _sort_number + 1;
if (next_id is not null) then
update tester set is_open = 1 where id = next_id;
end if;
end//
delimiter ;
I think this should work - i haven't tested on your table structure, and it does assume a unique primary key on your table. If it doesn't have that - it's easy enough to modify.
To use it, just call completeandopen(id of the row to be completed) (after changing the table name from tester to your table name)

Related

update a table after inserting a value in the same table using triggers [duplicate]

I am running a MySQL Query. But when a new row is added from form input I get this error:
Error: Can't update table 'brandnames' in stored function/trigger because it is
already used by statement which invoked this stored function/trigger.
From the code:
CREATE TRIGGER `capital` AFTER INSERT ON `brandnames`
FOR EACH
ROW UPDATE brandnames
SET bname = CONCAT( UCASE( LEFT( bname, 1 ) ) , LCASE( SUBSTRING( bname, 2 ) ) )
What does this error mean?
You cannot change a table while the INSERT trigger is firing. The INSERT might do some locking which could result in a deadlock. Also, updating the table from a trigger would then cause the same trigger to fire again in an infinite recursive loop. Both of these reasons are why MySQL prevents you from doing this.
However, depending on what you're trying to achieve, you can access the new values by using NEW.fieldname or even the old values --if doing an UPDATE-- with OLD.
If you had a row named full_brand_name and you wanted to use the first two letters as a short name in the field small_name you could use:
CREATE TRIGGER `capital` BEFORE INSERT ON `brandnames`
FOR EACH ROW BEGIN
SET NEW.short_name = CONCAT(UCASE(LEFT(NEW.full_name,1)) , LCASE(SUBSTRING(NEW.full_name,2)))
END
The correct syntax is:
FOR EACH ROW SET NEW.bname = CONCAT( UCASE( LEFT( NEW.bname, 1 ) )
, LCASE( SUBSTRING( NEW.bname, 2 ) ) )
A "BEFORE-INSERT"-trigger is the only way to realize same-table updates on an insert, and is only possible from MySQL 5.5+. However, the value of an auto-increment field is only available to an "AFTER-INSERT" trigger - it defaults to 0 in the BEFORE-case. Therefore the following example code which would set a previously-calculated surrogate key value based on the auto-increment value id will compile, but not actually work since NEW.id will always be 0:
create table products(id int not null auto_increment, surrogatekey varchar(10), description text);
create trigger trgProductSurrogatekey before insert on product
for each row set NEW.surrogatekey =
(select surrogatekey from surrogatekeys where id = NEW.id);
#gerrit_hoekstra wrote: "However, the value of an auto-increment field is only available to an "AFTER-INSERT" trigger - it defaults to 0 in the BEFORE-case."
That is correct but you can select the auto-increment field value that will be inserted by the subsequent INSERT quite easily. This is an example that works:
CREATE DEFINER = CURRENT_USER TRIGGER `lgffin`.`variable_BEFORE_INSERT` BEFORE INSERT
ON `variable` FOR EACH ROW
BEGIN
SET NEW.prefixed_id = CONCAT(NEW.fixed_variable, (SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'lgffin'
AND TABLE_NAME = 'variable'));
END
I have the same problem and fix by add "new." before the field is updated. And I post full trigger here for someone to want to write a trigger
DELIMITER $$
USE `nc`$$
CREATE
TRIGGER `nhachung_province_count_update` BEFORE UPDATE ON `nhachung`
FOR EACH ROW BEGIN
DECLARE slug_province VARCHAR(128);
DECLARE slug_district VARCHAR(128);
IF old.status!=new.status THEN /* neu doi status */
IF new.status="Y" THEN
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id;
ELSE
UPDATE province SET `count`=`count`-1 WHERE id = new.district_id;
END IF;
ELSEIF old.province_id!=new.province_id THEN /* neu doi province_id + district_id */
UPDATE province SET `count`=`count`+1 WHERE id = new.province_id; /* province_id */
UPDATE province SET `count`=`count`-1 WHERE id = old.province_id;
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id; /* district_id */
UPDATE province SET `count`=`count`-1 WHERE id = old.district_id;
SET slug_province = ( SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1 );
SET slug_district = ( SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1 );
SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district);
ELSEIF old.district_id!=new.district_id THEN
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id;
UPDATE province SET `count`=`count`-1 WHERE id = old.district_id;
SET slug_province = ( SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1 );
SET slug_district = ( SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1 );
SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district);
END IF;
END;
$$
DELIMITER ;
Hope this help someone

how to update this stored procedure?

this is my code to update 2 table in stored procedure
DROP PROCEDURE IF EXISTS `SP_ENGG_UPDATE_ITEM_SERVICE`;
DELIMITER $$
CREATE PROCEDURE `SP_ENGG_UPDATE_ITEM_SERVICE`(
IN `p_uid` BIGINT(20) UNSIGNED,
IN `p_sid` BIGINT(20) UNSIGNED,
IN `p_sdid` BIGINT(20) UNSIGNED,
IN `p_mediaJson` TEXT,
IN `p_itemStatus` TINYINT(1),
IN `p_mediavalue` TEXT)
BEGIN
DECLARE stcount int DEFAULT 0;
DECLARE ttcount int DEFAULT 0;
SET #updated = 0;
IF(p_sid > 0 && p_sdid > 0 ) THEN
UPDATE user_service_details SET
p_mediavalue = p_mediaJson,
status = p_itemStatus
WHERE user_service_id = p_sid AND id =p_sdid;
SET stcount = (SELECT count(*) FROM user_service_details WHERE user_service_id = p_sid AND status = 2 );
SET ttcount = (SELECT count(*) FROM user_service_details WHERE user_service_id= p_sid );
IF (stcount = ttcount) THEN
UPDATE user_service SET
status= 4
WHERE id = p_sid AND engg_id = p_uid ;
END IF;
SET #updated = 1;
END IF;
SELECT #updated;
END
this is my query to update
call SP_ENGG_UPDATE_ITEM_SERVICE(252317018022627,25231702221634,252302221637,
'{"images":["img1.png","img2.png","img3.png"],"videos":["vid1.mp4","vid2.mp4","vid3.mp4"],"audios":["aud1.mp3","aud2.mp3","aud3.mp3"]}',2,'before_image');
when I am trying to update this error is showing:-
Error Code: 1054 Unknown column 'p_mediavalue' in 'field list'
Any one have any idea how to update.
The column name user_service_details in Table user_service_details is wrong as per the error thrown "Unknown column name".

Update in mysql trigger not working

I'm creating a trigger to execute after an insert is done into my checkin table but my update statement is not working
DELIMITER $$
DROP TRIGGER IF EXISTS checkins_AINS$$
CREATE TRIGGER `checkins_AINS` AFTER INSERT ON `checkins` FOR EACH ROW
BEGIN
DECLARE client_id INT;
DECLARE duplicate_record INTEGER DEFAULT 0;
DECLARE bpoints INT;
DECLARE business_id INT;
DECLARE CONTINUE HANDLER FOR 1062 SET duplicate_record = 1;
SELECT checkinPoints, id INTO bpoints, business_id FROM businesses WHERE id = new.venue_id;
INSERT INTO clients_checkins_summary(client_id, venue_id, first_checkin, last_checkin,visits)
VALUES(new.client_id, new.venue_id, new.createAt, new.createAt,1);
INSERT INTO clients_points_summary(client_id, business_id,current_points)
VALUES(new.client_id, business_id,bpoints);
IF duplicate_record = 1
THEN
UPDATE clients_checkins_summary
SET last_checkin = new.createAt,
visits = visits + 1
WHERE client_id = new.client_id and venue_id = new.venue_id;
UPDATE clients_points_summary
SET current_points = current_points + bpoints
WHERE client_id = new.client_id and business_id = business_id;
END IF;
END$$
DELIMITER ;
Inserting:
insert into checkins(client_id,venue_id,points,createAt,updateAt)
values (52,19,1,now(),now());
for the first time works fine but when the case of update is trigger is entering into the if but is not update the value.
I trace the variables into a table and all the values are correct but update is not been updating anything.
I missing something?
am I missing something?
Possibly this
UPDATE clients_points_summary
SET current_points = current_points + bpoints
WHERE client_id = new.client_id and business_id = business_id;
The problem here is that your local variable business_id and the column name clients_points_summary.business_id are ambiguous. You could disambiguate as follows:
UPDATE clients_points_summary cps
SET cps.current_points = cps.current_points + bpoints
WHERE cps.client_id = new.client_id and cps.business_id = business_id;

Cannot set variable in trigger

I am trying to set a variable in a trigger that is the most recent entry in the table. However, PHPMyAdmin notes there is an error at line SET clicked_campaign_id =. I do not see the problem here.
CREATE TRIGGER tr_user_action_click
AFTER INSERT ON users_click FOR EACH ROW
BEGIN
DECLARE clicked_campaign_id int
SET clicked_campaign_id =
(SELECT campaignId
FROM users_click
WHERE id = (SELECT max(id) FROM users_click));
Update onlineportal.`campaigns`
SET `clicks` = `clicks` + 1
WHERE id = clicked_campaign_id;
END
Is there a different way to set a variable...?
You must set the DELIMITER in phpMyAdmin, as shown in the image:
Then, create the trigger:
CREATE TRIGGER `tr_user_action_click` AFTER INSERT ON `users_click`
FOR EACH ROW
BEGIN
DECLARE `clicked_campaign_id` INT;
SET `clicked_campaign_id` =
(SELECT `campaignId`
FROM `users_click`
WHERE `id` = (SELECT max(`id`) FROM `users_click`));
UPDATE `onlineportal`.`campaigns`
SET `clicks` = `clicks` + 1
WHERE `id` = `clicked_campaign_id`;
END//

MySQL insert trigger with multiple inserts at the same time

I'm trying to generate a primary key for my table, something like this
(simplified version) - the purpose is to have a daily incremented key:
DELIMITER ^
CREATE TABLE `ADDRESS` (
ID INTEGER NOT NULL DEFAULT -1,
NAME VARCHAR(25),
PRIMARY KEY(`ID`))^
CREATE FUNCTION `GETID`()
RETURNS INTEGER
deterministic
BEGIN
declare CURR_DATE DATE;
declare maxid, _year, _month, _day, newid INTEGER;
set CURR_DATE = CURRENT_DATE;
set _year = EXTRACT(YEAR FROM CURR_DATE);
set _mon = EXTRACT(MONTH FROM CURR_DATE);
set _day = EXTRACT(DAY FROM CURR_DATE);
set newid = (_year - (_year/100) * 100) * 10000 + _mon * 100 + _day;
select max(ID) into maxid From `ADDRESS`;
if (maxid is null) then
set maxid = 0;
end if;
if (MAXID / 1000 != newid) then
set MAXID = newid * 1000;
end if;
set MAXID = MAXID + 1;
return MAXID;
END^
CREATE TRIGGER `ADDRESS_ID_TRIGGER` BEFORE INSERT ON `ADDRESS`
FOR EACH ROW
BEGIN
if new.id=-1 then
set new.id = getid();
end if ;
END^
COMMIT^
DELIMITER ;
Generally it works fine, but when I test it with multiple inserts at the same time
it obviously fails (e.g. no dirty reads, the select max will fail for the 2nd insert,
thus it will generate the same id as fro the 1st insert).
Workaround:
Make primary key AUTO_INCREMENT.
Add TIMESTAMP field and use BEFORE INSERT/UPDATE trigget to set CURRENT_TIMESTAMP().
Also you can use ON UPDATE CURRENT_TIMESTAMP option for TIMESTAMP field, value will be updated automatically.
So, ID is ID, and TIMESTAMP field contains date and time.