MySql trigger, update another table on insert - mysql

I've already, searched and read, many answers about this issue , but couldn't get a clear answer on how to do this.
My query is the following:
DELIMITER //
CREATE TRIGGER `Stock_Update` AFTER INSERT ON `Store_db`.`Product_Supply` FOR EACH ROW
BEGIN
UPDATE `Store_db`.`Stock` AS `ST`
SET `ST`.`Stock_Quantity` = `ST`.`Stock_Quantity` + `Product_Supply`.`Supply_Quantity`
WHERE `ST`.`Product_ID` = `Product_Supply`.`Product_ID`;
END//
DELIMITER ;
Thanks In Advance.
P.S. A More Generic Answer would be nice too and might be helpful for others as well

From within a trigger on a given table, all references to fields of this table must be prefixed by either NEW. or OLD., which refers respectively to the value of this field after or before the change.
In your case, you probably want to add the newly inserted quantity to your existing stock: use NEW.Supply_Quantity (do not mention Product_Supply, this is already implied by the NEW keyword).
Likewise, you certainly want to use NEW.Product_ID in your condition.
Notice that NEW is not available in a trigger on deletion, like OLD in a trigger on insertion.

Related

Using a trigger to automatically assign a value to specific column on a new insert

I'm struggling to find proper information on SQL Triggers.
My previous question got removed for it not being specific enough so hopefully this will do better.
I am trying to create a trigger that will assign RoleID 1 to every newly inserted row to my users table.
But I can't seem to figure it out.
AFTER INSERT on users
on EACH ROW
insert into users.RoleID values(1);
This doesn't seem to work.
And the examples and or information regarding triggers all focus on alerts or sending emails after an insert/drop or update.
Can it actually be done?
Any help would be much appreciated.
Cheers!
It looks like you aren't creating you sql trigger with the correct keyword.
Try this
drop trigger if exists before_insert_users;
DELIMITER $$
CREATE TRIGGER before_insert_users
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
SET NEW.RoleID = 1;
END$$
DELIMITER ;
Note: RoleID will need to actually be a column on your table for this to work.
However, a trigger is not the best way to do this... See this SO post : Add a column with a default value to an existing table in SQL Server

Use mysql triggers to backup row after updating events

I found this question MYSQL Trigger Update Copy Entire Row
Where the suggestion to use the following code answer partially to my personal question to perform a row backup after altering a DB row:
DROP TRIGGER auditlog
CREATE TRIGGER auditlog AFTER UPDATE ON frequencies
FOR EACH ROW BEGIN
INSERT INTO frequencies_audit select * from frequencies where freqId = NEW.freqId;
END;
The problem is that I like to insert additional information to the backuped row so I thought that add variables could do the trick. My question is, is this the right procedure?
INSERT INTO frequencies_audit select *, #variable, 'my_value' from frequencies where freqId = NEW.freqId;
I know this question is old, but I stumbled upon exactly the same question. For me, just adding the missing fields directly like in:
INSERT INTO frequencies_audit select *,"insert" as operation from frequencies where id = NEW.id
worked fine for me. For more realistic cases, you would have to join.

MYSQL Change Values based on Table values (Constraint or Trigger?)

Quick few questions on MYSQL syntax, it seems extremely hard to find these answers on google. Is it possible to set a constraint or trigger so that when a value of a column reaches a certain point it get's reset and something else is done. Or also if say hourLog is greater than zero, then licence status changes from Default value of INVALID to Valid.
I know all this could be done with a program that was using the database, but was just curious if there were MYSQL commands to do this automatically with a trigger or a Constraint.
Sorry if this was posted, I just was looking for quick clarification for a class.
You could use these two triggers, one for the UPDATE, one for the INSERT:
CREATE TRIGGER upd_yourtable BEFORE UPDATE ON yourtable
FOR EACH ROW
SET new.licenseStatus=
CASE WHEN new.hourLog>0 THEN 'Valid' ELSE 'INVALID' END
;
CREATE TRIGGER ins_yourtable BEFORE INSERT ON yourtable
FOR EACH ROW
SET new.licenseStatus=
CASE WHEN new.hourLog>0 THEN 'Valid' ELSE 'INVALID' END
;
Please see fiddle here.

How to sync values in a table column in mysql trigger

I need to sync values in a table column in mysql trigger while having the same value in another column. Here is an example of my table:
id___MP____sweek
1____2_____1
2____2_____1
3____1_____2
4____1_____2
5____3_____3
6____3_____3
If a user changes, for example, MP in the first row (id=1) from 2 to 4, then the value of MP with the same sweek has to be changed (e.g., id=2, MP becomes also 4).
I wrote a BEFORE UPDATE tigger that does not work:
USE moodle;
DELIMITER $$
CREATE TRIGGER trigger_course_minpostUPD BEFORE UPDATE ON moodle.mdl_course_sections FOR EACH ROW
BEGIN
IF NEW.MP <> OLD.MP THEN
BEGIN
SET #A=NEW.MP;
SET NEW.MP = #A
WHERE OLD.sweek=NEW.sweek;
END;
END IF;
END$$
DELIMITER ;
From within a MySQL trigger you are not able to affect other rows on the same table.
You would want to say something like:
UPDATE my_table SET MP=NEW.MP WHERE sweek = NEW.sweek
But - sorry - no go.
There are hack around this -- and ugly ones, too.
If your table is MyISAM, you can wrap it up with a MERGE table, and act on the MERGE table instead (MySQL doesn't realize at that point you're actually hacking around it).
However, using MyISAM as a storage engine may not be a good thing -- today's focus is on InnoDB, a much more sophisticated engine.
Another trick is to try and use the FEDERATED engine. See relevant post by Roland Bouman. Again, this is a dirty hack.
I would probably let the application do the thing within the same transaction.

MySQL: trigger with clause "instead of update"

I'm trying to create a database with history in mind (experience shows you'll have to do this one day or another).
I've asked here database-design-how-to-handle-the-archive-problem but there's no better anser than the link here.
My problem is about where to do the code and technically, how (MySQL gives me headaches). First I've started doing this in Php: before doing any insert, duplicate the record mark it as "obsolete" then modify the record.
But there's a dependency problem (manytomany and manytoone associations must be updated as well) which implies coding (one way or another) all the dependancies and updates that come with the tables (which is not acceptable).
So I'm thinking about doing all the work on the database server side. This would greatly simplify my Php code.
The problem is that I have to "archive" the current record before modifying it. To do so, the code must be in a trigger "before update".
Here's my code:
DELIMITER ;;
DROP TRIGGER IF EXISTS produit_trigger_update_before;
CREATE TRIGGER produit_trigger_update_before
BEFORE UPDATE ON produit
FOR EACH ROW BEGIN
/* */
INSERT INTO produit SET
id_origine = OLD.id_origine,
date_v_creation = OLD.date_v_creation,
date_v_start = OLD.date_v_debut,
date_v_end = NOW(),
...
last_record = OLD.last_record;
/* Dependancies : */
SET #last=LAST_INSERT_ID();
UPDATE categorie_produit SET id_produit=#last
WHERE id_produit = OLD.id;
UPDATE produit_attribut SET id_produit=#last
WHERE id_produit = OLD.id;
END;;
DELIMITER ;;
If I get this code working, all my problems are gone. But damn it, it's not working:
mysql> update produit set importance=3;
ERROR 1442 (HY000): Can't update table 'produit' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
mysql> Bye
In this page there's a working sample, which uses INSTEAD OF UPDATE clause in the trigger. MySQL doesn't seem to support this.
So my question is both conceptual (= have you any other "principle" that could work) and/or technical (= can you make this trigger work).
If I get this code working, all my problems are gone. But damn it, it's not working:
As a rule you can't have a trigger on table A trigger inserts into table A - since that could cause an endless loop. (Trigger mutation in Oracle terms)
Personally I would not do this using triggers. Triggers can do "audit logging" - but this is not what you want here.
I suggest you solve it programatically - either with a PHP function or a MySQL stored procedure (whatever your preference) that you call something like "ModifyProduit".
The code would then do basically what you have the trigger above do. (It might be easier to just have the code set date_v_end on the current row, and then insert a completly new row. That way you don't have to mess around with updating your referenced tables)
you can do history of a table with an auxiliary table like this (i've done this for many tables on mysql and the speed is very good):
table produit_history has the same structure as produit + 2 additional columns: "history_start DATETIME NOT NULL" and "history_stop DATETIME DEFAULT NULL".
there are 3 triggers on produit table:
AFTER INSERT: in this trigger there is a simple insert into produit_history of the same data with history_start = NOW() and history_stop = NULL (NULL means the current row is valid)
AFTER UPDATE: this trigger performs two queries. The first is un update like this:
UPDATE produit_history set history_stop = NOW() WHERE id_origine = OLD.id_origine AND history_stop IS NULL;
The second query is an insert identical to the one in the AFTER INSERT trigger.
AFTER DELETE: this triggers there is a simple update which is identical to the one in the AFTER UPDATE.
You can then query this history table and obtain snapshots at whatever time you're interested in with the following where condition:
WHERE (history_start &lt= "interesting_time" AND (history_stop IS NULL OR history_stop &gt "interesting_time"))