Make trigger update the rows I want - mysql

I am struggling with a trigger to update a second table based on the first table being updated.
I have tried this:
DELIMITER //
FOR EACH ROW
BEGIN
Update phpfb_picks
set points = NEW.value
where username = user and gameid = gameid
END;
//
delimiter;
but get an error about syntax.
If I do:
Update phpfb_picks
set points = NEW.value
where username = user and gameid = gameid
This works to a point. It updates all users records with the same value that was updated.
What I want to do is, when a value is updated on Table A, I want to update Table B with all records for that user, basically the 'value' from table A would always be pushed to 'points' of table B for the user, regardless if the actual record was updated.
If any record for user is updated, update all of table B records with the same value based on the username and gameid
So if Table A has the following records:
username - test
gameid - 1
value - 1
username - test
gameid - 2
value - 2
when value from row 1 is updated to 3, i want to update Table B with all the current values from table A for that user.
Is this even possible?
UPDATE:
Table A (allpoints) has columns:
username
gameid
value
TABLE B (phpfb_picks) has columns:
user
gameid
points
allpoints.username = phpfb_picks.user
allpoints.gameid = phpfb_picks.gameid
allpoints.value = phpfb_picks.points
Whenever an update is made to allpoints, I want all the records for that specific user to update all the specific records for that user in phpfb_picks, passing the allpoints.value to phpfb_picks.points based on the user and gameid

Try this trigger:
DELIMITER $$
CREATE TRIGGER update_phpfb_picks
AFTER UPDATE ON allpoints FOR EACH ROW
BEGIN
UPDATE phpfb_picks
INNER JOIN allpoints ON allpoints.username = phpfb_picks.username AND
allpoints.gameid = phpfb_picks.gameid
SET phpfb_picks.points = allpoints.value
WHERE phpfb_picks.username = NEW.username;
END;
$$
DELIMITER ;
For each row that is updated in allpoints, all rows in phpfb_picks with the same username of the updated row will be updated to the respective value of points present in allpoints as value. The trigger is an AFTER UPDATE so that the newly updated value in allpoints will also be set in phpfb_picks.

Maybe this
drop trigger if exists phpfb;
DELIMITER $$
create trigger phpfb after update on allpoints
FOR EACH ROW
BEGIN
Update phpfb_picks
set points = NEW.value
where user = new.username and gameid = new.gameid;
END $$
delimiter ;
for example
drop table if exists allpoints,phpfb_picks;
create table allpoints (username char(4),gameid int, value int);
create table phpfb_picks (user char(4),gameid int, points int);
insert into allpoints (username,gameid) values
('test',1),('test',2);
insert into phpfb_picks (user,gameid) values
('test',1),('test',1),('test',2);
update allpoints
set value = 2 where username = 'test' and gameid = 1;
result
+------+--------+--------+
| user | gameid | points |
+------+--------+--------+
| test | 1 | 2 |
| test | 1 | 2 |
| test | 2 | 0 |
+------+--------+--------+
3 rows in set (0.00 sec)

Related

MySQL relationship schema

Assuming MySQL with a users table like
id | user_name | total_likes | updated_at
and a likes table like
id | user_id | like
What I need is to when the likes table gets updated/inserted/deleted then the users.updated_at associated with likes.user_id gets updated to the current date. Further when an insert happens to the likes table, then users.total_likes increases by 1 value.
I can do all the above with queries however, I am trying to use the power of relationships in MySQL. Please can you advise?
As David mentioned above, you are most likely looking for triggers. Something like this:
Delimiter //
CREATE TRIGGER ai_likes AFTER INSERT ON likes
FOR EACH ROW
BEGIN
INSERT INTO users (updated_at) VALUES
NOW()
WHERE id = NEW.id;
UPDATE users SET total_likes = (total_likes + 1)
WHERE id = NEW.id;
END//
Delimiter ;
CREATE TRIGGER au_likes AFTER UPDATE ON likes
FOR EACH ROW
INSERT INTO users (updated_at) VALUES
NOW()
WHERE id = NEW.id;
CREATE TRIGGER ad_likes AFTER DELETE ON likes
FOR EACH ROW
INSERT INTO users (updated_at) VALUES
NOW()
WHERE id = NEW.id;

Table trigger to indicate two records were merged

I have some simple triggers on a table which work for to audit changes to a record by logging to a table any time an INSERT, UPDATE, or DELETE occurs. When a record is inserted into Users, a copy is made in Users_History with a Status field populated with the value 'INSERT'. Same is done for UPDATE and DELETE.
DELIMITER $$
CREATE TRIGGER Users_History_Insert AFTER INSERT ON Audit
FOR EACH ROW BEGIN
INSERT INTO Users_History select *, 'INSERT' from Users where ID = NEW.ID;
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER Users_History_Delete BEFORE DELETE ON Audit
FOR EACH ROW BEGIN
INSERT INTO Users_History select *, 'DELETE' from Users where ID = OLD.ID;
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER Users_History_Update AFTER UPDATE ON Audit
FOR EACH ROW BEGIN
INSERT INTO Users_History select *, 'UPDATE' from Users where ID = NEW.ID;
END$$
DELIMITER ;
We have a function where two Users records can be merged with each other. Effectively, all values of one record are overwritten with the values of another record, and the unchanged record is deleted.
If you had a table such as this:
| ID | Name | email |
| 1 | Billy | bill#mail.com |
| 2 | Bill | bill2#mail.com |
And I wanted to merge record 2 into 1, I'd end up with this result.
| ID | Name | email |
| 1 | Bill | bill2#mail.com |
I'd like to create a trigger that would have this in Users_History where 2 is the record merged from.
| Users_ID | Name | Email | Status |
| 1 | Bill | bill2#mail.com | MERGED:2 |
As it stands now, we would end up with two records, an UPDATE and a DELETE
UPDATE `Users_To`
SET `Name` = `Users_From`.`Name`, `email` = `Users_From`.`email`
FROM `Users` AS `Users_To`
CROSS JOIN `Users` AS `Users_From`
WHERE `Users_To`.`ID` = 1 AND `Users_From`.`ID` = 2;
DELETE FROM `Users` WHERE `ID` = 2;
I can't think of a way to do this in SQL, is it possible? As I understand, the triggers have no knowledge of the JOIN or WHERE clause affecting a record.
Your UPDATE query has a flaw and is correctly
UPDATE `Users` AS `Users_To` CROSS JOIN `Users` AS `Users_From`
SET `Users_To`.`Name` = `Users_From`.`Name`, `Users_To`.`email` = `Users_From`.`email`
WHERE `Users_To`.`ID` = 1 AND `Users_From`.`ID` = 2;
DELETE FROM `Users` WHERE `ID` = 2;
What the trigger does is simple first it check if the update is a modify of an existing row by checking if there are mor than one rows with the same email.
If that the case grab the other id in your case 2 and add it ti the text.
This works as long you have only 2 rows involved in your update query.
And i don't know your your table, but if you have a UNIQUE constraint you will have a problem with the update.
DELIMITER $$
DROP TRIGGER IF EXISTS Users_History_Update;
CREATE TRIGGER Users_History_Update AFTER UPDATE ON users
FOR EACH ROW BEGIN
SELECT Count(*) INTO #number FROM Users WHERE `email` = NEW.`email`;
IF #number > 1 THEN
SELECT `ID` INTO #id FROM Users WHERE `email` = NEW.`email` AND `ID` <> NEW.`ID`;
INSERT INTO Users_History VALUES (OLD.`ID`,OLD.`Name` ,OLD.`email`, CONCAT('MERGED:',#id));
ELSE
INSERT INTO Users_History VALUES (OLD.`ID`,OLD.`Name` ,OLD.`email`, 'UPDATE');
END IF;
END$$
DELIMITER ;

How would I create this trigger?

I have two tables that look like this (of course they have a lot more rows).
AuthorID | Name | Number of albums
-------------------------------------------
1 | Santana | 39
2 | Johnny Cash | 95
AuthorID | AlbumID
----------------------
1 | 14
2 | 17
What I want to do is have a trigget that gets updated when there is a row deleted or inserted into the second table. The row I want to update in the first table is the 3rd row. Which basically represents count(AlbumID) that is also how I have calculated it. I don't really know how I would do that since until now I only created really simple triggers
It's not at all clear why you need to store a number_of_albums column in the first place. But I won't address that question. I'll answer the question you asked.
An after insert trigger on the second table can perform an update the first table, to increment the number_of_albums column for the given author_id. We'll assume the name of the first table is author and the name of the second table is album.
DELIMITER $$
CREATE TRIGGER album_ai
AFTER INSERT ON album
FOR EACH ROW
BEGIN
UPDATE author
SET number_of_albums = number_of_albums + 1
WHERE author_id = NEW.author_id;
END$$
DELIMITER ;
You could do something similar with an after delete trigger, decrementing the number_of_albums column, referencing OLD.author_id to get the value of the author_id column of the row that is deleted.
For an update, if the value of the author_id column is changed, you would need to update two rows... increment number_of_albums on one row, and decrement number_of_albums the other.
DELIMITER $$
CREATE TRIGGER album_ai
AFTER UPDATE ON album
FOR EACH ROW
BEGIN
IF NOT ( NEW.author_id <=> OLD.author_id ) THEN
UPDATE author
SET number_of_albums = number_of_albums - 1
WHERE author_id = OLD.author_id;
UPDATE author
SET number_of_albums = number_of_albums + 1
WHERE author_id = NEW.author_id;
END IF;
END$$
DELIMITER ;

How to create a trigger that adds a new row to another table and a reference to the new row added to present table?

I have this relation (A):
ID | B_ID
This relation (B):
ID | FOO
I want to add a trigger to A which will, on insertion of a new row into A (with B_ID always set as NULL), add a row in B with FOO set as NULL and set the B_ID attribute in the new row of A to reference the newly added B row.
Example:
Right after insertion into
A:
1 | NULL
After trigger action:
A:
1 | 555
B:
555 | NULL
Is this possible?
You can try something like the following:
/* Trigger structure for table `a` */
DELIMITER $$
CREATE TRIGGER `trg_a_bi` BEFORE INSERT ON `a`
FOR EACH ROW
BEGIN
INSERT INTO `b` (`foo`) VALUES (NULL);
SET NEW.`b_id` := LAST_INSERT_ID();
END$$
DELIMITER ;
Here a SQL Fiddle.

How do I do this MYSQL trigger between 2 tables?

For example If I had 2 columns on TABLE1 called "id" and "count" that contains numbers in "count" column, when those numbers reach 50 or over then I want the trigger to update a column called "reached" on TABLE2 with "yes" along with its id, in the id column
How can it be done? Thanks
delimiter |
CREATE TRIGGER table1_trigger AFTER UPDATE ON table1
FOR EACH ROW BEGIN
IF NEW.count >= 50
then
update table2 set reached = 'yes' where id = NEW.id;
end if;
END;
|