MySQL trigger for change detection - mysql

I have several tables in the database: Users, Profiles, Articles
I also have one table called Changes, which is used for administrative purposes. This table consists of id, table_name, and date_created.
What I need to do is whenever something is added, deleted or updated in a regular table (Users, Profiles, Articles), create a new row in the Changes with the name of the updated table and the current timestamps.
I've been browsing for a while and tried many different methods, but nothing really worked. I know the solution should be very simple, may be someone can help me. Thank you for your time.

So in this case you need 9 trigger 3 for each of the regular table after insert, after update, after delete
Here is for one table you can write for the others
When you insert on Users
delimiter //
create trigger log_user_insert after insert on Users
for each row
begin
insert into Changes (table_name,date_created) values ('Users',now());
end; //
delimiter ;
When update happens on Users
delimiter //
create trigger log_user_update after update on Users
for each row
begin
insert into Changes (table_name,date_created) values ('Users',now());
end; //
delimiter ;
When delete happens on Users
delimiter //
create trigger log_user_update after delete on Users
for each row
begin
insert into Changes (table_name,date_created) values ('Users',now());
end; //
delimiter ;
I would suggest to add a column called action in the table Changes and to insert each action name as well i.e. insert,update and delete.

You need to create an update, insert and delete trigger on each of the data tables:
CREATE TRIGGER upd_changes_users BEFORE UPDATE ON Users
FOR EACH ROW
BEGIN
INSERT INTO changes (table_name, date_created) VALUES ('users', NOW());
END;
This code assumes, that the id column in changes is auto_generated. You might also want to consider including a type column in the changes table (to differentiate between insert, update and delete).

Related

How to create 'before insert' trigger that looks at multiple tables

I am struggling to understand the format to create an 'insert before' trigger that must meet conditions of other tables.
For example, if I have a table named 'borrowed' that I would like to insert values into but must meet conditions from another table called 'member'. The condition is that MemberStatus = 'regular'. If this condition passes, I will be able to run a 'insert into borrowed' but if the conditions aren't met then it will not be able to pass.
This is how I previously understood the concept but after hours of reading i've become confused. Any help would be appreciated.
delimiter //
drop trigger if exists trigger1
//
create trigger trigger1
before insert on borrowed
for each row
begin
if...
end if;
end;
//

SQL trigger for add some data

Thank you for your help.
I have 3 tables on MySQL. One Table for my users and second is for my user features, the third one is for roles. First of all, I need to add registration on a measures table when the user is inserted. I mean if I add a new user to tbl_users the trigger will grab the user id and write on the tbl_measures that's it. I need just this.
INSERT INTO tbl_measures (user_id) VALUES (tbl_users.id)
this my triggers it is working partly. when I add a new user trigger add a new line to tbl_measures without id.
When you refer NEW.id in your insert trigger, there are two main cases. In the first case you get the proper id value. This is what you expect. In the second case it's null. This is what happens.
Essential is whether the trigger runs before or after the insert. Before the insert the id does not exist, because the record was not created yet. After the insert the id exists. Long story short code:
DELIMITER //
CREATE TRIGGER PROOFOFCONCEPT
AFTER INSERT
ON EACH ROW
BEGIN
INSERT INTO tbl_measures(user_id)
VALUES (NEW.id);
END; //
DELIMITER ;
I found the solution:
CREATE TRIGGER `after_members_insert` AFTER INSERT ON `tbl_users`
FOR EACH ROW BEGIN
INSERT INTO tbl_measures(user_id)
VALUES(new.id);
END

Mysql - Create trigger to insert a new row based on a row inserted in another table

Hi I have two tables called users and userrewards. When a new row gets inserted into the users table, I want to take the userid and create a new row in the userrewards table, only if the usertype is "premium". In the userrewards table I just need to insert the userid - the rest of the fields are set to default values until the user makes changes themselves. How can I do this via a trigger?
You need to create an "after instert" trigger on user: that's the table you're watching. Now, if I guessed your column names correctly, the sql for creating the trigger should look like this:
CREATE TRIGGER user_ai AFTER INSERT ON user
FOR EACH ROW
BEGIN
IF new.usertype = 'premium' THEN
INSERT INTO userrewards (user_id) VALUES new.id;
END IF;
END;
Another example of a trigger with if statements and :old / :new values can be found here. MySQL documentatation for create trigger here. MySQL documentation for the if-syntax here.

MySQL select statement result in after delete trigger always null

I'm having a little issue with a trigger in a MySQL database. I have a DB with two tables: "tasks" and "files". The "tasks" table have a field which is a foreign key of the primary key from the "files" table. It also sometimes may be null.
What I'm trying to acomplish is to delete in the first place a row in the "tasks" table, and after that delete the corresponding row in the "files" table using a trigger.
This is the trigger I'm using right now:
DELIMITER //
CREATE TRIGGER after_delete_file AFTER DELETE ON tasks
FOR EACH ROW
BEGIN
DECLARE fileId int;
SELECT file INTO fileId FROM tasks WHERE id=old.id;
DELETE FROM files WHERE id=fileId;
END;//
DELIMITER ;
The field "file" in the "tasks" table is the one containing the foreign key. In the examples I've been running, that field has never been null.
The problem is that the select statement always returns null. The delete statement that triggers this trigger goes fine, but the row in the "files" table is never deleted. I've tried to insert the "fieldId" variable on a testing table, and it's always saving a null value.
Is there any problem on that trigger? Maybe I'm trying to do something merely impossible?
All the help is much appreciated :)
Since it should be looping over each deleted row, why would this not work?
DELIMITER //
CREATE TRIGGER after_delete_file AFTER DELETE ON tasks
FOR EACH ROW
BEGIN
DELETE FROM files WHERE id=old.file;
END;//
DELIMITER ;
If that doesn't work, could try this:
DELIMITER //
CREATE TRIGGER after_delete_file AFTER DELETE ON tasks
FOR EACH ROW
BEGIN
DELETE FROM files INNER JOIN tasks ON files.id=tasks.file WHERE tasks.id=old.id;
END;//
DELIMITER ;
but I don't think that should be necessary.
AFTER delete means that the data is deleted, of course you can't find it. Try creating the trigger for BEFORE delete.
You could also more carefully use all of the old values rather than selecting from the table that was deleted from.

Is there any version control in mysql?

It is possible to use a version control system with mysql databases?
Or, is there a version control system already implemented?
I want to say e.g.: SELECT foo FROM bar WHERE version = X
Whereeby version is a mysql internal colum with last update date.
Very late response... similar to Ruben's suggestion, I have setup triggers to update a version_control table to increment version number every time there is an INSERT, UPDATE & DELETE.
I laid out the steps on my site mradamfrancis.tumblr.com
** update **
I’ve decided to use triggers to assist with version control. Here’s how…
I have a table containing players, if there are changes (INSERT, DELETE, or UPDATE) I want to increment the version number in my version_control table.
This is how the version_control table looks:
version_id (key), table_name (varchar), version (integer)
I then create 3 triggers on the players table, one for INSERT, DELETE & UPDATE.
INSERT:
delimiter //
CREATE TRIGGER `player_table_INSERT` AFTER INSERT ON `players`
FOR EACH ROW BEGIN
UPDATE version_control SET version=version+1 WHERE table_name=’players’;
END;//
delimiter ;
DELETE:
delimiter //
CREATE TRIGGER `player_table_DELETE` AFTER DELETE ON `players`
FOR EACH ROW BEGIN
UPDATE version_control SET version=version+1 WHERE table_name=’players’;
END;//
delimiter ;
UPDATE:
delimiter //
CREATE TRIGGER `player_table_UPDATE` AFTER UPDATE ON `players`
FOR EACH ROW BEGIN
UPDATE version_control SET version=version+1 WHERE table_name=’players’;
END;//
delimiter ;
** I have additional SQL statements in the FOR EACH section of the trigger, hence I’ve used delimiter (1st line and last line) along with BEGIN & END.
You could also define extra tables for logging. For instance if you already have a table news, you can duplicate it as news_log. then add columns for logging data such as: modified date, action (update, delete, add) and so on.
next you define triggers on the original tables that will insert the data into your logging table. for instance when you update a record in you news table the news_log_trigger that you define is executed and a new record is inserted into new_log with the action value "UPDATE" and the current date as modified date.
for more info on mysql triggers:
http://dev.mysql.com/doc/refman/5.0/en/triggers.html
In case you want to do this for every project you can problably write a generic stored procedure to do the actual logging. that way you can reuse it and you only have to define the triggers and logging tables.