MySQL trigger needs tweaking - mysql

I have a trigger that sets a datetime field in a table row when a new row is inserted. (Don't bother lecturing me that I could do this in the table definition, I have second datetime field that is using that functionality already and you can only do it with one column per table.)
This trigger works great for my purposes:
CREATE TRIGGER foobar_insert
BEFORE INSERT ON foobar
FOR EACH ROW SET NEW.created=NOW();
So whenever a new row is inserted, foobar.created gets set to the current time. This is great when I do something like:
INSERT INTO foobar (foo) VALUES ('bar');
The only problem with this is that if I want to explicitly set foobar.created in the insert statement, it gets overridden by the trigger.
So,
INSERT INTO foobar (foo,created) VALUES ('foo','2006-01-01 12:12:12');
results in foobar.created equaling the time of the insert, not the time specified in the insert statement.
So my question is: How can I change my trigger to only set foobar.created if it doesn't already have a value?
EDIT:
In response to james_bond below, here is what worked:
DELIMITER $$
DROP TRIGGER IF EXISTS foobar_insert$$
CREATE TRIGGER foobar_insert
BEFORE INSERT ON foobar
FOR EACH ROW
IF NEW.created IS NULL THEN
SET NEW.created=NOW();
END IF$$
DELIMITER ;
Note I had to include DELIMITER statements because the IF statement required an interior semicolon.

Test for NEW.created is NULL, if is set it's because you have set it in your insert statement,if it is NULL then it needs the current time as value, something like this will do the trick:
if NEW.created is NULL THEN
SET NEW.created = now();
end if

Related

mysql trigger to update the same table from another table

I'm trying to set up a trigger which will update same row by inserting some additional data from another table. Field receive.iccid is blank, and I want it to be updated on every insert. However this trigger doesn't work
delimiter //
CREATE TRIGGER ins_iccid
AFTER INSERT ON receive
FOR EACH ROW
BEGIN
UPDATE receive SET NEW.iccid = (SELECT goip.iccid FROM goip WHERE NEW.goipname=goip.name);
END//
delimiter ;
turns out that I need to use 'BEFORE INSERT' to achieve what i was trying to
CREATE TRIGGER `ins_iccid` BEFORE INSERT ON `receive`
FOR EACH ROW
BEGIN
SET NEW.iccid = (SELECT goip.iccid FROM goip WHERE NEW.goipname=goip.name);
END

Firing a MySQL trigger on existing table upon creation of trigger

I have a table with 2 columns named "Table1":
(Column 1 named "Col1" with the values: A,B,C,D,E,F)
(Column 2 named "Col2" with the values: 12,15,2,5,200,1).
I would like get all the values from column 2 to change to the value 1 if their value is lower than 100, so that column 2 will eventually look like this:
(Column 2 named "Col2" with the values: 1,1,1,1,200,1).
I tried to create a trigger:
delimiter //
CREATE TRIGGER Table1upd BEFORE UPDATE ON Table1
FOR EACH ROW
BEGIN
IF NEW.Col2<100 THEN
SET NEW.Col2=1;
END IF;
END;//
delimiter ;
When creating the trigger in MySQL workbench it says that the trigger was added but that 0 row(s) affected.
I assume my problem is with the BEFORE UPDATE choice, because the trigger does work when I update a value in the table, but I don't know what to change it to so that the trigger will also initially execute automatically when I create it.
Thank you in advance for any help,
D
The answer is simple: a BEFORE UPDATE trigger only triggers on UPDATE, so you need a second trigger BEFORE INSERT to cover both use cases: update and insert:
delimiter //
CREATE TRIGGER Table1insert BEFORE INSERT ON Table1
FOR EACH ROW
BEGIN
IF NEW.Col2<100 THEN
SET NEW.Col2=1;
END IF;
END;//
delimiter ;

How can I Update column value to Old value plus New value from other table using Trigger?

How can I Update column value to Old value plus New value from other table using Trigger if that value has already have an entry?
What I wanted is something like the following. Notice the bold and italicized part.
DELIMITER$$
CREATE TRIGGER trigger_name AFTER INSERT
ON table_one FOR EACH ROW
BEGIN
INSERT INTO table_two(clmn_id, clmn_one) VALUES(NEW.clmn_id_fk,NEW.clmn_a)
ON DUPLICATE KEY UPDATE clmn_one = VALUES(clmn_one + NEW.clmn_a);
END$$
DELIMITER;
Try removing the keyword VALUES from the ON DUPLICATE KEY:
DELIMITER$$
CREATE TRIGGER trigger_name AFTER INSERT
ON table_one FOR EACH ROW
BEGIN
INSERT INTO table_two(clmn_id, clmn_one) VALUES(NEW.clmn_id_fk,NEW.clmn_a)
ON DUPLICATE KEY UPDATE fine_amount = clmn_one + NEW.clmn_a;
END$$
DELIMITER;
Looks like you need a select statement first, to check if it already exists. If so, set variables to current values, then run an update that combines the old values (variables) and new values. If the record doesn't already exist, run insert statement with current values.

Trigger after insert points to the wrong last_insert_id()

I am running this trigger
DELIMITER //
CREATE TRIGGER lestrigger
AFTER INSERT ON examinations
FOR EACH ROW
BEGIN
DECLARE the_last_inserted_id INT;
SELECT LAST_INSERT_ID() INTO the_last_inserted_id;
END //
DELIMITER ;
After insert,the last_inserted_id variable holds the last_insert_id of the previous insert instead of the current.
To fix this,i did SELECT LAST_INSERT_ID()+1 INTO the_last_inserted_id; but this is not really a fix since i don't know why the trigger is not working as it should.There is a similar question here but i don't understand it.Should i always add 1 to my trigger like the way i have done it?.
No, don't add 1 to last_insert_id() in the trigger.
In a multi-user, multi-threaded environment, you have no guarantee (and no expectation) that this will get you the id value that was assigned to the row that was just inserted. (An INSERT statement can insert more than one row, and a value for ID can be supplied so that it is not auto-generated.)
If what you want is the value that was actually assigned to the id column of the row that was just inserted (whether that was auto-generated, or whether the INSERT statement inserted more than one row), the do this:
SET the_last_inserted_id = NEW.id;
That gets the actual value that was assigned to the row (in an AFTER UPDATE FOR EACH ROW trigger. In a BEFORE UPDATE ... FOR EACH ROW trigger, this value could actually be modified.)
The behavior you are observing isn't wrong; it's what we expect. The behavior of the LAST_INSERT_ID() function is well documented here:
http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_last-insert-id

MySQL trigger after update on the same table

I have a MySQL trigger using the BEFORE INSERT ON table that calculates a value and updates the same table after a user inserts values in specific columns. This works as expected. But a user makes a mistake in their entry and fixes their error and I want to write a trigger that will update the calculated value after the error has been fixed. Is there a way to achieve this?
A BEFORE UPDATE ON table trigger has access to the existing values in the row as well as newly supplied values, and can set the value of any column in the table, based on whatever conditions and expressions we want.
For example, it's possible to test whether the value of one or more columns of concern has been modified, and then set some other column to some expression.
DELIMITER $$
CREATE TRIGGER my_before_update_trigger
BEFORE UPDATE ON my_table
FOR EACH ROW
BEGIN
IF NOT ((NEW.col1 <=> OLD.col1) AND (NEW.col2 <=> OLD.col2)) THEN
SET NEW.col3 = NEW.col1 * NEW.col2 ;
END IF;
END$$
DELIMITER ;