UPDATE Same Row After UPDATE in Trigger - mysql

I want the epc column to always be earnings/clicks. I am using an AFTER UPDATE trigger to accomplish this. So if I were to add 100 clicks to this table, I would want the EPC to update automatically.
I am trying this:
CREATE TRIGGER `records_integrity` AFTER UPDATE ON `records` FOR EACH ROW SET
NEW.epc=IFNULL(earnings/clicks,0);
And getting this error:
MySQL said: #1362 - Updating of NEW row is not allowed in after trigger
I tried using OLD as well but also got an error. I could do BEFORE but then if I added 100 clicks it would use the previous # clicks for the trigger (right?)
What should I do to accomplish this?
EDIT - An example of a query that would be run on this:
UPDATE records SET clicks=clicks+100
//EPC should update automatically

You can't update rows in the table in an after update trigger.
Perhaps you want something like this:
CREATE TRIGGER `records_integrity` BEFORE UPDATE
ON `records`
FOR EACH ROW
SET NEW.epc=IFNULL(new.earnings/new.clicks, 0);
EDIT:
Inside a trigger, you have have access to OLD and NEW. OLD are the old values in the record and NEW are the new values. In a before trigger, the NEW values are what get written to the table, so you can modify them. In an after trigger, the NEW values have already been written, so they cannot be modified. I think the MySQL documentation explains this pretty well.

Perhaps you could write two separate statements in that transaction
update record set clicks=...
update record set epc=...
or you could put them inside a function, say updateClick() and just call that function. By doing it this way you can easily alter your logic should the need arise.
Putting the logic inside a trigger might create a situation where debugging and tracing are made unnecessarily complex.

Related

What is proper way to set and compare variable inside an sql trigger

Am populating a table using a trigger after an insert event occurs on another table and that worked fine. However i then noticed that the trigger would still insert a new row for existing records. To fix this, I want to create the trigger again but this time it would only fire if a condition is met...but not having previously used triggers in the past am getting a syntax error and not able to identify what am doing wrong. Kindly have a look and help me fix this
CREATE TRIGGER `students_gen_insert`
AFTER INSERT ON `students` FOR EACH ROW
BEGIN
INSERT INTO records (student_id, subject_id)
SELECT new.student_id, subjects.subject_id
FROM subjects
WHERE category = new.class;
END;
Am currently using MySql 5.6.17 version.
It is generally not a good idea to SELECT from the table the trigger is on, and forbidden to UPDATE or INSERT (not that you are doing those). Assuming you are trying to get the values for the row just inserted, the first SET ... SELECT you have is needless; just use NEW.fieldname to get the fields of the inserted row.
The second SET ... SELECT and following condition are a bit confusing. If referential integrity is being maintained, I would think it would be impossible for the records table to refer to that particular student_id of the students table at the point the trigger is executed. Perhaps this was to avoid the duplicate inserts from the trigger's previous code? If so, it might help for you to post that so we can pinpoint the actual source of redundant inserts.

How can I create multiple BEFORE INSERT triggers?

I'm trying to learn mysql more in depth with relationships, triggers and what not. I currently have these 2 triggers for my database:
I'm trying to add another one that will BEFORE INSERT a different table
But I keep getting this error:
I'm not sure how I can get around this, or if this is specific to Sequel Pro (The GUI I'm using), it seems to wrap the query internally so I only have to enter the basic stuff, is there any way I can get this to work? My schema is like:
Forum_Threads has many Forum_Posts
Forum_Posts has many Posts_Replies
Forum_Threads and Forum_Posts both have a reply counter, so I'm trying to increment / decrement the reply_count on both tables when I'm inserting or deleting replies. Thanks.
The issue is that the GUI is trying to do a create trigger on a table that already has a before insert type trigger. Check your "Forum_threads" table to see if there's a BEFORE UPDATE trigger already on it.
Prior to MySQL 5.7.2,
There cannot be multiple triggers for a given table that have the same
trigger event and action time. For example, you cannot have two BEFORE
UPDATE triggers for a table. But you can have a BEFORE UPDATE and a
BEFORE INSERT trigger, or a BEFORE UPDATE and an AFTER UPDATE trigger.
(see 13.1.19 CREATE TRIGGER Syntax from the 5.6 manual.)
You can, however, specify multiple actions within the body of a given trigger, although the one-trigger-per-event limit can make managing trigger actions inconvenient.
it is not possible to 'create' multiple BEFORE INSERT triggers, but a possible workaround for you would be setting a behavior for each type of event.
Something like this may help you:
DROP TRIGGER IF EXISTS `<your_trigger>`;
DELIMITER //
CREATE TRIGGER `<your_trigger>` BEFORE INSERT ON `<your_table>`
FOR EACH ROW BEGIN
CASE <your_identifier>
WHEN <first_type> THEN
/*
ACTION BLOCK
FOR THIS EVENT
*/
WHEN <second_type> THEN
/*
ACTION BLOCK
FOR THIS EVENT
*/
ELSE
/*
ACTION BLOCK
FOR THIS EVENT
*/
END;
END//
DELIMITER ;
You can add as many event type as you needed, by doing this you can create a trigger that has multiple action based on a given event type identifier.
I hope this can help you, cheers!

UPDATE my_table doesn't work correctly

I'm using the following query to replace old link with a new one:
UPDATE my_table SET file = 'link' WHERE my_table.file ='old_link';
In my tests I can't duplicate that and I'm not sure what's wrong with that query, but apparently sometimes it leaves the old entry and inserts a new one instead of updating!
mysql ver:
5.6.12-56 Percona Server, table type: innodb
The query looks fine to me. UPDATE should never create new rows, only modify existing rows. The problem is probably in another part of the code.
Although an UPDATE won't fire an insert in its own, there could exist triggers in the database that would fire an INSERT whenever a record gets updated.
Here are some links that you should check:
CREATE TRIGGER Syntax
Trigger Syntax and Examples

MySQL: update without changing data, possible?

Is it possible in MySQL to update a row, without changing any data?
I just need a trigger to do its work, but the data should not be changed.
Of course I could do an update and then another update, but the trigger is quite slow (deletes and inserts 500 rows everytime) and I have to update thousands of rows, so I'd rather not do it twice.
I could also just update a dummy field with NOW(), but I'm just curious if it's possible without 'tricks'.
How about:
UPDATE table SET id=id WHERE ...
You should just be able to run an UPDATE command with the same data that already exists in the row. No data will change, but the trigger will still fire.

MySQL Trigger - INSERT on condition of UPDATE

I'm trying to find the most effecient way of inserting data into another table when a particular field is updated on trigger table. The INSERT should only occur on a specific type of update.
The table on which I want to create the trigger is named incremental. The table I'm inserting into is named crm_record
On incremental there is a field called status. By default when a record is initially added to the table the status field is set to new. After billing has processed that value changes to processed. So once this occurs I want to INSERT into crm_record, only if the value of another field (success) is set to 1.
I have considered using both CASE and IF but would like an expert's opinion on the best way to do this.
Ok, I eventually went with this that seemed to work. Thanks for pointing me in the right direction
CREATE TRIGGER `incremental5_after_ins_tr_crmm` AFTER UPDATE ON `incremental5`
FOR EACH ROW
BEGIN
IF Status = 'processed' AND Success = 1 THEN
INSERT INTO crm_master (msisdn,source,contract_type,revenue) VALUE (new.msisdn,'INC5',new.contract_type,revenue=revenue+2.5)
ON DUPLICATE KEY UPDATE contract_type=new.contract_type,revenue=revenue+2.5;
END IF;
END;
All you need to do is to create an AFTER UPDATE trigger and test the value of status and success together. If it's going only going to be one state you're testing for then an IF statement would be the simplest way to go about it.
However before implementing a trigger it's always worth going back a step and checking to see if the row in crm_record shouldn't actually be inserted via the code logic when the status and success columns are updated.