MYSQL AFTER Trigger UPDATE IF - mysql

I want to UPDATE my row after it has been updated by the user.
Example if after the user selects 32, and Principal previously entered is > 1000. Then Update the 32 to 40.
CREATE TRIGGER updateusers_id AFTER UPDATE ON Table
FOR EACH ROW
BEGIN
IF(NEW.users_id = 32 AND Table.Principal > 50000) THEN
UPDATE loans SET users_id = 40;
END IF;
END

Think about it for a second and you'll realize the first problem: if what you actually need here is an AFTER update trigger... then what would a BEFORE update trigger do?
AFTER UPDATE means after the update query has already changed the row data. What you are actually looking to is BEFORE UPDATE -- you want to hijack the update in mid-stream, before the table data actually gets changed, and potentially modify the values that will actually be written to the database.
UPDATE loans SET users_id = 40;
There are two problems with this. First, you know what an UPDATE without WHERE does... right? It updates all the rows in the table. Luckily, the server didn't let you do that. But the solution is not to add a WHERE clause -- it's this:
IF(NEW.users_id = 32 AND NEW.Principal > 50000) THEN
SET NEW.users_id = 40;
END IF;
The NEW pseudotable contains the row data that the user has tried to cause the UPDATE (that fired the trigger) to write to the row. You are in a BEFORE UPDATE ... FOR EACH ROW trigger, so setting NEW values overrides anything the user tried to do... which appears to be what you are wanting to accomplish.

Related

How to determine if a row is going to be updated within an update query not using trigger or table definition

I want to update a column in MySQL only if the row is updated. (meaning all the other values trigger mysql to update the row.)
It's a concatenated text-field, so automatic calculation using ON UPDATE in the table definition won't work.
A trigger won't work either since the value is not fixed.
If there is ON UPDATE in table definition or triggers, there must be a way to determine that in some expression, right?
(Of course, I could create/update a trigger every time after the update or do a second update based on automatic update timestamp (which I then need to select first...) but that's both not very effective nor elegant.)
What I'd love to do would be something like this:
UPDATE tbl
SET x = 1, y = 2
ON UPDATE ( z = CONCAT_WS(', ',z,'blah') );

Trigger to change all the rows after an update is done

Having a table with the name transitions, I want to change the values of all the rows after any update is made.
I'm using the following trigger, which changes only the ROW that I'm making the update to.
CREATE TRIGGER signaturetrigger BEFORE UPDATE ON `transactions` FOR EACH ROW
BEGIN
SET New.signature = '288';
END
I'm trying to change all the rows to signature = 288, how can I modify the trigger in order to archieve that? I thought that using FOR EACH ROW would be enough.
Thanks in advance.
You can use an after update trigger with an update statement:
CREATE TRIGGER signaturetrigger AFTER UPDATE ON `transactions`
FOR EACH ROW
BEGIN
UPDATE transactions
SET New.signature = '288';
END;
This does seem like a very strange thing to do, however.
Consider an alternative: just add an UpdatedAt column into the table and update the signature in that row. Then, when you want the most recent signature use:
select signature
from transactions
order by UpdatedAt desc
limit 1;
An index on transactions(UpdatedAt, signature) will make this quite speedy. And, the update will go much, much faster than updating all rows.

PL SQL Trigger to update start time for row when a single column is updated

I'm fairly new to triggers and have already tried searching for a solution to my question with little results. I want to update a single row's start time column whenever it's active column is set to 1.
I have two columns ACTIVE (number) and START_TIME (timestamp) in my_table. I would like to create a PL/SQL trigger that updates the START_TIME column to current_timestamp whenever an update statement has been applied to the ACTIVE column - setting it to 1.
So far I have only seen examples for inserting new rows or updating entire tables which isn't what I'm looking to do. I'd have thought there would be a fairly simple solution to my problem.
This is what I've got so far from other examples. I know the structure of my solution is poor and I'm asking for any input to modify my trigger to achieve my desired result.
CREATE OR REPLACE TRIGGER routine_active
AFTER UPDATE ON my_table
FOR EACH ROW
WHEN (my_table.ACTIVE = 1)
begin
insert my_table.start_time = current_timestamp;
end;
\
you can use like this .it may help you
write the update query instead of insert query
CREATE OR REPLACE TRIGGER routine_active
AFTER UPDATE ON my_table
FOR EACH ROW
WHEN (new.ACTIVE = 1)
begin
update my_table set start_time =current_timestamp;
end;
I think it should be a BEFORE UPDATE, not AFTER UPDATE, so it saves both changes with a single action. Then you don't need the INSERT or UPDATE statements. I also added the "OF active" clause, so it will only start this trigger if that column was updated, which may reduce the workload if other columns get updated.
CREATE OR REPLACE TRIGGER routine_active
BEFORE UPDATE OF active ON my_table
FOR EACH ROW
BEGIN
IF active = 1
THEN
:NEW.start_time = current_timestamp;
END IF;
END;

MySQL Trigger for Aging

I'm trying to create a trigger that will automatically increase the year column by 1 when the month column is 12, and then empty the month column.
But I don't understand triggers that well and I'm confusing myself in my attempts, so I was hoping someone could look over this code to see if it would work or suggest improvements:
CREATE TRIGGER aging BEFORE UPDATE ON dogs
FOR EACH ROW
DELETE FROM dogs WHERE month = 12;
UPDATE year SET year = year+1;
Thanks!
Two things to point out...
First, a trigger is clearly the wrong choice for what you want to do. Not only because the trigger can be avoided by calculating the age on the fly based on birth of date. But also, because a trigger only affects the rows that are affected by the corresponding statement. Don't be fooled by the FOR EACH ROW. You write something like
UPDATE table SET whatever = whatever WHERE month = 12;
and all the rows where month = 12 is true are affected. What you seem to want to do, is to update the whole table to check if in some rows your condition is true. Not only is this a performance nightmare, you are also restricted to one trigger (per event) per table. Meaning you can have i.e. one BEFORE UPDATE and 1 AFTER UPDATE but not 2 BEFORE UPDATE.
The second thing to note is, that you can't issue an UPDATE statement in an UPDATE trigger. This would cause an infinite loop :)
Instead you use the aliases NEW and OLD. NEW refers to the value of a column given by the UPDATE statement and OLD refers to the value of the column before the UPDATE statement was executed.
In your case (althoug it's hopefully clear by now, that you shouldn't use the trigger in this case), one would write the trigger like this:
Given this initial statement
UPDATE myTable SET whatever = whatever;
which updates the whole table, this trigger
DROP TRIGGER IF EXISTS [whatever you call this thing];
DELIMITER ##
CREATE TRIGGER aging BEFORE UPDATE ON dogs
FOR EACH ROW
IF (month = 12) THEN /*month refers to the column here, not a variable like in Gordon's answer*/
SET NEW.year = OLD.year+1;
SET NEW.month = 1;
END IF;
END ##
would update the columns correctly.
I've never created a trigger before, but I just read through the docs. This is my attempt...
DELIMITER ||
DROP TRIGGER ID EXISTS [whatever you call this thing]
||
DELIMITER ##
CREATE TRIGGER aging BEFORE UPDATE ON dogs
FOR EACH ROW
DECLARE month integer;
IF (month = 12) THEN
-- DELETE FROM dogs WHERE month = 12;
-- this will delete the record; probably not what you want
UPDATE year SET year = year+1;
UPDATE month SET month = NULL;
END IF;
END;
##

How can I get an after update trigger to work when it is being fired from an after insert trigger in mysql?

Hello, every one :)!
I'll try and keep this as simple as possible, basically, I have one table that references itself via a parent_id column. Each row in the table can have a parent and can keep count of how many children it has via the count column. So essentially what I'm trying to do is have the triggers update each parent row's count column when necessary
The problem is that the update trigger gets called when the update operation in the insert trigger gets called. Then I get:
"General error: 1442 Can't update table 'term_taxonomies' in stored function/trigger because it is already used by statement which invoked this stored function/trigger".
Any ideas?
Actual code:
TRIGGER `dbname`.`ai_term_taxonomies`
AFTER INSERT ON `dbname`.`term_taxonomies`
FOR EACH ROW
BEGIN
IF NEW.parent_id NOT 0 THEN
UPDATE term_taxonomies as termTax SET assocItemCount = (assocItemCount + 1)
WHERE termTax.term_taxonomy_id = NEW.parent_id;
END IF;
END$$
CREATE
TRIGGER `dbname`.`au_term_taxonomies`
AFTER UPDATE ON `dbname`.`term_taxonomies`
FOR EACH ROW
BEGIN
IF NEW.parent_id NOT OLD.parent_id THEN
IF NEW.parent_id NOT 0 THEN
UPDATE term_taxonomies as termTax SET assocItemCount = (assocItemCount + 1)
WHERE termTax.term_taxonomy_id = NEW.parent_id;
END IF;
IF OLD.parent_id NOT 0 THEN
UPDATE term_taxonomies as termTax SET assocItemCount = (assocItemCount - 1)
WHERE termTax.term_taxonomy_id = OLD.parent_id;
END IF;
END IF;
END$$
All mysql triggers execute in the same transaction as the triggering statement.
You want to update using the SET NEW.assocItemCount syntax as opposed to performing an UPDATE statement on the underlying table.
Edit: However, in your case this is not possible because you are updating a different row in the same table, the hardest thing to do in a mysql trigger. Sorry.
You will have to change your schema. Take assocItemCount out of your table, create a new table holding just term_taxonomy_id and assocItemCount, and update that using an UPDATE statement from your query. It is also possible to use a view joining these two tables to hide this detail if a query needs to use your original schema.
Alternatively, if you did not have assocItemCount in your database at all, you would still be able to compute it in any queries, and your database would be better normalized than it is now.