How do I do this MYSQL trigger between 2 tables? - mysql

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;
|

Related

MySQL create trigger for logging table

Hello I am new for MySQL. I have 2 table, a data table and a log/history table. I would like to make a trigger, that put the old data from Data to Data_log if any of the column change on the Data. I made a trigger but I don't know how to check if the value of any column changes. Lately I would like to create some procedure/view which can return one line data on a specific date. Like return all field from ID 1 on 2022-03-27
Data:
ID
name
data
price
1
thing1
desc of t1
100
2
thing2
desc of t2
300
Data_log:
log_id
data_id
column_name
old_data
date
1
1
data
desc t1
2022-03-28 06:49:14
2
2
price
600
2022-03-28 11:34:46
3
1
price
4400
2022-03-28 09:15:54
Trigger (only check price column):
DELIMITER //
CREATE TRIGGER `log_old_data` BEFORE UPDATE ON `data`
INSERT INTO data_log
(
data_id,
old_data
)
VALUES
(
OLD.id,
OLD.price <- I need here a Select I think
);
END//
Since you have few columns, it may be simpler to do it "by hand" for every columns
DELIMITER //
CREATE TRIGGER `log_old_data` BEFORE UPDATE ON `data`
IF NEW.name != OLD.name THEN
INSERT INTO data_log (data_id, old_data) VALUES (OLD.id, OLD.name);
END IF;
IF NEW.data != OLD.data THEN
INSERT INTO data_log (data_id, old_data) VALUES (OLD.id, OLD.data);
END IF;
IF NEW.price != OLD.price THEN
INSERT INTO data_log (data_id, old_data) VALUES (OLD.id, OLD.price);
END IF;
END //
DELIMITER ;
PS: I did not test it, but it should work. If it doesn't, leave your mysql version to allow me to test on your version
For the SELECT part, since yo record every change on a separate table you only have to do a query on it
SELECT * FROM log_old_data WHERE `log_id` = 1 AND DATE(`date`) = '2022-03-27';
PS: Careful, DATE() on a WHERE condition may not be the perfect choice, it will not use indexes. I use generated columns to add index on date for this kind of case.

Fill Column of SQL Table

I'm trying to fill a certain column of a SQL table with data from another table. I have a column named "size" in my table which should return the number of rows in the 2nd table where the id of both rows is the same. Is there a way to populate a SQL column based on a certain command? I would love to be able to fill the column based on this command:
SELECT count(*)
FROM second_table
WHERE id = "row_id";
Here is a sample database with the two tables:
Table 1
Name
id
tiger
1
lion
2
gazelle
1
Here is the desired output for Table 2:
id
Number of Animals
1
2
2
1
I am trying to fill the Number of Animals column but do it automatically and dynamically when another row is added or deleted to Table 1, which is why I want the Select count(*) SQL statement as the code for the column.
One method is a correlated subquery:
update table1 t1
set size = (select count(*)
from table2 t2
where t2.id = t1.id
);
If you need to do this dynamically (as data is inserted), then you would need to use a trigger. However, I would suggest that you calculate the value as needed, unless there is a specific reason why you need to store it.
I guess you need something like this:
CREATE TRIGGER UpdateAnimalCountTable2
AFTER INSERT ON `Table1` FOR EACH ROW
begin
DECLARE NewCount int;
SELECT count(1)
INTO #NewCount
FROM Table1
WHERE Table1.id= NEW.id;
UPDATE Table2
SET NoOfAnimals = #NewCount
WHERE id = NEW.id;
END;
Above is the trigger which will be executed after every insert in Table1 and will update the count in Table 2 for ID which just got inserted in Table1.

Update field with another auto increment field value MySQL

I have a table in MYSQL database with two fields:
Id (auto increment field).
Post_Id.
When I insert a new record both fields should have the same value. So I should update post_id with Id value, and at the same time make sure that I update the field with the right value not with any other new inserted record value.
I tried this SQL statement but it was very slow and I was not sure that I select the right value:
set #auto_id := (SELECT AUTO_INCREMENT
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='table_name'
AND TABLE_SCHEMA=DATABASE() );
update table_name set post_id= #auto_id where id=#auto_id ;
I don't have long experience with MySQL and I cannot change the table structure .
The approach you followed is not transaction safe as well.
The best option I can think about is to use trigger
Edit: According to #lagripe's mentionings
CREATE TRIGGER sometrigger
AFTER INSERT ON sometable
BEGIN
SET NEW.post_id := (SELECT id from sometable order by DESC limit 1) + 1 ; // you may need +1 here. I couldn't test it.
END
or you may consider to use LAST_INSERT_ID
insert into table_name values ( .... );
update table_name set post_id = LAST_INSERT_ID();
but why do you need two columns with the same id at first place?
if you really need why don't you use computed/generated columns?
CREATE TABLE Table1(
id DOUBLE,
post_id DOUBLE as (id)
);
you can use triggers :
CREATE TRIGGER UpdatePOST_id
BEFORE INSERT ON table_db
FOR EACH ROW
SET NEW.post_id := (select id from table_db order by id DESC LIMIT 1)+1 ;
from now on, whatever you insert your as a value in post_id column will be replaced with the id inserted automatically.
Test :
|id|post_id|
|20| 20 |
|21| 21 |
|22| 22 |
|23| 23 |
To drop the trigger :
DROP trigger UpdatePOST_id

Make trigger update the rows I want

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)

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 ;