Create trigger to generate expiration date from foreign value - mysql

I have a trigger that should calculate the expiration date of a subscription based on what subscription-type you've chosen
DROP TRIGGER IF EXISTS `trigger_expiration_date`;
CREATE DEFINER=`root`#`localhost`
TRIGGER `trigger_expiration_date`
BEFORE
INSERT ON `contracts`
FOR EACH ROW update contracts c
inner join contract_types ct on c.id_contract_type = ct.id_contract_type
set c.expiration_date = date_add(c.date_of_purchase, INTERVAL ct.nr_months MONTH)
Whenever I run the code above it's approved, but as soon as I insert anything I'm told that I can't insert because the trigger is invoked

Indeed, you cannot perform updates like that on the same table that your trigger is operating on.
Instead use the new alias to reference the record that is being inserted. From the documentation:
Within the trigger body, you can refer to columns in the subject table (the table associated with the trigger) by using the aliases OLD and NEW. OLD.col_name refers to a column of an existing row before it is updated or deleted. NEW.col_name refers to the column of a new row to be inserted or an existing row after it is updated.
In your case, you can do it like this:
CREATE TRIGGER trigger_expiration_date
BEFORE INSERT ON contracts
FOR EACH ROW
SET new.expiration_date = (
SELECT date_add(new.date_of_purchase, INTERVAL nr_months MONTH)
FROM contract_types
WHERE new.id_contract_type = id_contract_type);

Related

How to use trigger to update only one row in table with Mysql

I have an after insert trigger that is supposed to update the field total in my table "test" where the id_cart is equal to new.id_cart. However my trigger is updating every single row in the table not only the one desired. I would like to know how can I modify my trigger so it only updates the row that I want.
This is my trigger.
CREATE DEFINER=`root`#`localhost` TRIGGER `update_total_test`
AFTER INSERT ON `test_product_quantity_cart`
FOR EACH ROW BEGIN
UPDATE test set total= (select sum(price_product) from test_product_quantity_cart where id_cart=new.id_cart);
END
So if the new row inserted in table "test_product_quantity_cart" has an new.id_cart=1, then only the row in table "test" with id_cart=1 should be uptated.
I think I am missing a "where" clause to indicate the update statement which rows it is suppossed to upate. However I do not know how to add that clause.
Thank you!
CREATE DEFINER=`root`#`localhost` TRIGGER `update_total_test`
AFTER INSERT ON `test_product_quantity_cart`
FOR EACH ROW
UPDATE test
JOIN ( SELECT id_cart, SUM(price_product) total
FROM test_product_quantity_cart
WHERE id_cart=NEW.id_cart ) value_for_update USING (id_cart)
SET test.total = value_for_update.total;

MYSQL Trigger to insert column value in same table

I have a mysql Innodb table 'classrooms_subjects' as
id|classroom_id|subject_id
classroom_id & subject_id are composite keys. Whenever i insert a row with classroom_id & subject_id, my id field is inserted as 0.
Now i want to create a trigger which will enter id field as last_inserted_id()+1.
Also I need to take care of multiple records inserted at a time. My trigger is like below:
CREATE TRIGGER `increment_id` AFTER INSERT ON `classrooms_subjects`
FOR EACH ROW BEGIN
UPDATE classrooms_subjects
SET classrooms_subjects.id = LAST_INSERT_ID() + 1 WHERE id=0;
END
when i am inserting a record I am getting the error as:
"Cant update table in trigger because it is already used by statement which invoked this trigger
For general info: using an update statement inside the trigger isn't right.
Better to use a before insert trigger and simply assign the value of your column using NEW.id
http://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html
A column named with OLD is read only. You can refer to it (if you have
the SELECT privilege), but not modify it. You can refer to a column
named with NEW if you have the SELECT privilege for it. In a BEFORE
trigger, you can also change its value with SET NEW.col_name = value
if you have the UPDATE privilege for it. This means you can use a
trigger to modify the values to be inserted into a new row or used to
update a row. (Such a SET statement has no effect in an AFTER
trigger because the row change will have already occurred.)
You should probably structure your table to make the auto_increment work properly. Better a solution that works when multiple sessions are inserting to the DB at once.

MySQL trigger INSERT all NEW columns

Is it possible to trigger the insert of all the columns for the NEW row? Basically, I want to make a copy of the newly insert record in another table but what having to specify all the columns.
Something like
DELIMITER $$
CREATE TRIGGER TestTrigger
AFTER INSERT
ON Table1 FOR EACH ROW
BEGIN
INSERT INTO `Table2` SELECT * FROM NEW;
END$$
DELIMITER ;
However this returns Table 'Database.NEW' doesn't exist whenever I try to insert a new row in Table1.
From MySQL documentation:
Within the trigger body, you can refer to columns in the subject table (the table associated with the trigger) by using the aliases OLD and NEW. OLD.col_name refers to a column of an existing row before it is updated or deleted. NEW.col_name refers to the column of a new row to be inserted or an existing row after it is updated.
Despite the time this question have been unanswered, you can SELECT all fields using primary key in source table if you have one.
CREATE TRIGGER replicated_table AFTER INSERT ON source_table FOR EACH ROW
BEGIN
INSERT INTO replicated_table SELECT * FROM source_table WHERE id=NEW.id;
END
Also, maybe you can prefer the use of REPLACE instead of INSERT to ensure the table will not stay out of sincronization.

trigger to maintain total

I have created some tables for invoicing.
There is a invoice_header and invoice_detail table. The invoice details contains in the invoice detail lines, invoice_header_id, qty, unit_price, tax_amount etc
The invoice header has the billing address, invoice no, invoice_total, etc
I have created a trigger for insert/update/delete so that the invoice_total in the header is the sum(invoice_details.qty * invoice_details.unit_price)
There is one case I am not sure how to cater for.
If I update an invoice_detail line, to associate it with a different header.
like this
UPDATE invoice_details SET invoice_header_id=1 WHERE invoice_header_id=2
The trigger will fire but it will update the old header record total but not the new one. How can I cater for that circumstance?
Wouldn't this work for you?
From Mysql trigger syntax
Within the trigger body, the OLD and NEW keywords enable you to access
columns in the rows affected by a trigger. OLD and NEW are MySQL
extensions to triggers; they are not case sensitive.
In an INSERT trigger, only NEW.col_name can be used; there is no old
row. In a DELETE trigger, only OLD.col_name can be used; there is no
new row. In an UPDATE trigger, you can use OLD.col_name to refer to
the columns of a row before it is updated and NEW.col_name to refer to
the columns of the row after it is updated.
A column named with OLD is read only. You can refer to it (if you have
the SELECT privilege), but not modify it. You can refer to a column
named with NEW if you have the SELECT privilege for it. In a BEFORE
trigger, you can also change its value with SET NEW.col_name = value
if you have the UPDATE privilege for it. This means you can use a
trigger to modify the values to be inserted into a new row or used to
update a row. (Such a SET statement has no effect in an AFTER trigger
because the row change will have already occurred.)
So, you would have OLD.invoice_header_id (2) and NEW.invoice_header_id (1) Inside the trigger for you to update invoice_header
CREATE TRIGGER check BEFORE UPDATE ON invoice_detail
FOR EACH ROW
BEGIN
IF NEW.invoice_header_id <> OLD.invoice_header_id THEN
You Do the math and update both invoice_header lines
END IF;
END

MySQL Trigger - Using logical inserted table to insert into another table

I am currently in the process of writing my first trigger in MySQL within PHPmyadmin. I would like it so that when an item in one table is updated, a row in another table is inserted. Several columns of the row that is to be inserted in the second table are determined by the values being updated in the first table.
Therefore, I need to INSERT a new row in table B when an update occurs on table A. And some of the values of the columns in table B are to be defined by the values in the updated table A row which caused the trigger to run.
Please find the trigger below.
CREATE TRIGGER `before_categoryiteminstance_update` BEFORE UPDATE ON `TABLEA`
FOR EACH ROW BEGIN
declare f_guidcategoryiteminstance int;
declare f_guidcategory int;
INSERT INTO TABLEB
SET
f_guidcategoryiteminstance =(SELECT guidcategoryiteminstance FROM inserted),
f_guidcategory =(SELECT guidcategory FROM inserted),
guiduser= f_guidcategory,
guidcategoryinstance= f_guidcategoryiteminstance,
number= number +1,
dateofaction= NOW(); END
The trigger can be added to the DB fine. However, when I attempt to update a row on table A (which should cause the trigger to run), I get an error stating that the table Inserted does not exist. However, I was under the impression that Inserted should be a logical table that contains the results of the initial part of the trigger. Is this only the case if the trigger is being run on an insert and not an update? If so, is there an equivalent for an update trigger?