I have the following snippet of an ER-diagram.
Whenever "order_item" is updated (i.e. when an item has been added to a 'shopping cart'), I want to decrement "Quantity" in the table "itemsinstock".
I know the syntax of a trigger (well, MySQL can also generate it) but I don't know how to do it. "order_item" needs to read ItemID from "itemsinstock" and based on that ID, it needs to decrement the quantity for that specific item. Is this possible?
Edit:
This is what I have now:
CREATE DEFINER=`root`#`localhost` TRIGGER
`orderdb`.`itemsinstock_AFTER_INSERT`
AFTER INSERT ON `order_item`
FOR EACH ROW
BEGIN UPDATE itemsinstock
SET Quantity = Quantity - order_item.itemQuantity WHERE itemID = ItemID; END
It gives me an error with "order_item.itemQuantity" .... It worked with "-1" but obviously I want it to decrement based on how many "itemQuantity" is. How do I do this?
Pretty close
CREATE DEFINER=`root`#`localhost` TRIGGER
`orderdb`.`itemsinstock_AFTER_INSERT`
AFTER INSERT ON `order_item`
FOR EACH ROW
BEGIN
UPDATE itemsinstock
SET Quantity = Quantity - NEW.itemQuantity WHERE itemID = NEW.id;
END
notice how order_item (which isn't defined) is being replaced by NEW which represents the row that was inserted. Also as a side note since this is a single statement you don't need begin end blocks
Related
I need some help with getting the syntax right to define a trigger in PHPmyAdmin.
What I have:
2 tables - invoice and invoiceitem
tbl_invoice has a field 'Total' which should show the sum of the 'Extended' price of the table invoiceitem
tbl_invoiceitem has 2 triggers that update the 'Extended' before_insert and before_update
What I try to accomplish:
Calculate the sum of all items for an invoice and update the 'Total' price in tbl_invoice after either new items are inserted or if the price or quantity for an existing item was updated.
I try to do this in PHPmyAdmin.
The error message is
I hope somebody can give mt a hint into the right direction. Just started with triggers and don't seem to find solution with a couple of days searching the internet.
Thank you for help in advance.
Cheers, Oliver
I can see 2 syntax errors in your code:
The delimiter commands should be outside of the trigger definition, not inside of it. Phpmyadmin should take care of this.
The commands within the begin ... end block should be terminated by semicolon (;), not by whatever you provide in the delimiter command.
I did not check if your sql commands within the trigger make sense, but the where condition of the set command does not seem right.
Ok, found a work around:write the full create trigger statement in a file and import with PHPmyAdmin. As 'Shadow' pointed out there was also a problem in the where conditions.
Below the corrected triggers that worked in my scenario.
There is a lot of examples on the net to get triggers done with the mysql client. This way you can use the exact syntax that you would type into a client and than import into PHPmyAdmin in case you can't reach the server your using with a command shell client.
Hope this helps other newbies.
Cheers, Oliver
-- after_insert trigger for InvoiceItem to Calculate the Total in Invoice
------------------------------------------------------------------------
DELIMITER //
CREATE TRIGGER `InvoiceItem_After_Insert` AFTER INSERT ON `invoiceItem`
FOR EACH ROW
BEGIN
SET #InvoiceNumber = NEW.InvoiceFK;
SET #ItemTotal = (SELECT SUM(Extended) FROM InvoiceItem WHERE InvoiceFk = #InvoiceNumber);
UPDATE Invoice SET Total = #ItemTotal WHERE id = #InvoiceNumber;
END
//
DELIMITER ;
-- after_update trigger for InvoiceItem to Calculate the Total in Invoice
------------------------------------------------------------------------
DELIMITER //
CREATE TRIGGER `InvoiceItem_After_Update` AFTER UPDATE ON `invoiceitem`
FOR EACH ROW
BEGIN
SET #InvoiceNumber = NEW.InvoiceFK;
SET #ItemTotal = (SELECT SUM(Extended) FROM InvoiceItem WHERE InvoiceFk = #InvoiceNumber);
UPDATE Invoice SET Total = #ItemTotal WHERE id = #InvoiceNumber;
END
//
DELIMITER ;
-- after_delete trigger for InvoiceItem to Calculate the Total in Invoice
----------------------------------------------------------------------
DELIMITER //
CREATE TRIGGER `InvoiceItem_After_Delete` AFTER DELETE ON `invoiceItem`
FOR EACH ROW
BEGIN
SET #InvoiceNumber = OLD.InvoiceFK;
SET #ItemTotal = (SELECT SUM(Extended) FROM InvoiceItem WHERE InvoiceFk = #InvoiceNumber);
UPDATE Invoice SET Total = #ItemTotal WHERE id = #InvoiceNumber;
END
//
DELIMITER ;
-----------------------------------------------------------------
The next 2 triggers are just single statement and are calculate the 'Extended' column in the InvoceItem table
---------------------------------------------------------------------
-- Calculate new 'Extended' price before insert
CREATE TRIGGER `InvoiceItem_Before_Insert` BEFORE INSERT ON `invoiceitem`
SET NEW.Extended = ROUND(NEW.Quantity * NEW.Price,2)
-------------------------------------------------------------------
-- Calculate new 'Extended' price before update
CREATE TRIGGER `InvoiceItem_Before_Update` BEFORE UPDATE ON `InvoiceItem`
FOR EACH ROW
SET NEW.Extended = ROUND(NEW.Quantity * NEW.Price,2);
I have this reservation table that has RESERVATION_ID , ROOM_NUM, Date_Start , Date_End and cost columns. what I want to do is insert all the columns except cost and fill the cost automatically.
delimiter //
CREATE TRIGGER upd_check before INSERT ON reservation
FOR EACH ROW
BEGIN
IF NEW.RESERVATION_COST = NULL THEN
SET NEW.RESERVATION_COST = 'timestampdiff(day, NEW.RESERVATION_STARTD, NEW.RESERVATION_ENDD)*70';
END IF;
END;//
delimiter ;
I wrote this trigger to do it, but whenever I press Apply to insert everything nothing is inserted to the RESERVATION_COST column.
why?
I would put this in a comment if I had enough reputation, but anyways. Triggers cannot act on the same table which activated them. Seems limiting, but we've had the same issue.
This link doesn't explicitly say this but it does say "in the associated table". Not the same: https://dev.mysql.com/doc/refman/5.0/en/triggers.html
You can't compare a value to NULL, you need to check if it IS NULL instead.
e.g.
IF NEW.RESERVATION_COST IS NULL THEN
Well here is the problem...I want to update the inventory table at my database which includes
Sale(ProductID,Quantity,Price)
Invlevel(ProductID,Quantity)
I want to use triggers for this update. I have to use 2 triggers (I think). 1 at the sale tables which will be something like
CREATE TRIGGER `sale_AINS` AFTER INSERT ON sale FOR EACH ROW
begin
update Invlevel set quantity = Invlevel.quantity-"sale.quantity" where
Invlevel.ProductID = "sale.ProductID";
END
with this trigger, when a sale comes up, I want to adjust the inventory level at the product which the sale came to. However, even though this trigger has no errors and runs properly when I insert into sale table, it doesn't make any changes at the Invlevel table and I don't know why ( :# ).
Moreover, I made the trigger at the Invlevel table like that
CREATE TRIGGER `invlevel_AUPD` after UPDATE on invlevel FOR EACH ROW
if invlevel.quantity < 20
begin
insert into orders
(select productid,amount from reorder where reorder.productid = invlevel.productid )
end
*(orders,reorder are other tables)
It says to me I have syntax error which I don't know what it is and also even if I find it I can't even check the logic because the other trigger isn't even working... Any thought or help about it would be really helpful.
Try
First trigger
CREATE TRIGGER sale_AINS
AFTER INSERT ON sale
FOR EACH ROW
UPDATE invlevel
SET quantity = quantity - NEW.quantity
WHERE productid = NEW.productid;
In this trigger you don't need BEGIN END block since there is only one statement. In order to access column values or a row(s) that being inserted you need to use NEW keyword.
And the second one
DELIMITER $$
CREATE TRIGGER invlevel_AUPD
AFTER UPDATE ON invlevel
FOR EACH ROW
BEGIN
IF NEW.quantity < 20 THEN
INSERT INTO orders (productid, amount)
SELECT productid, amount
FROM reorder
WHERE productid = NEW.productid;
END IF;
END$$
DELIMITER ;
In the second trigger IF statement was out of BEGIN END block and syntax for IF was wrong. It should be IF ... THEN ... END IF;. And the same problems with a NEW keyword.
Here is SQLFiddle demo
You can put your IF condition into WHERE clause and make it more succinct like this
CREATE TRIGGER invlevel_AUPD
AFTER UPDATE ON invlevel
FOR EACH ROW
INSERT INTO orders (productid, amount)
SELECT productid, amount
FROM reorder
WHERE productid = NEW.productid
AND NEW.quantity < 20;
Here is updated SQLFiddle demo
How can I make trigger to read from two separated attribute in two different tables and then
calculate something .
this is the code I want to make but the mysql says it has problem
CREATE TRIGGER `fee_calculate` BEFORE INSERT ON `BookingRoom`
FOR EACH ROW BEGIN
SET NEW.fee = `Booking.Night_Qty` * `Room.RoomPrice` ;
END
I Think It Should Help You
I made some assumptions:
I assumed you wanted to update the reorders table with a productID that matches the Products table. (you can do an insert but may run into PK issues depending on how you have your table set up).
I assumed that the reorder amount will be placed there.
I did NOT include transaction statements, I would recommend adding these so it's logged.
CREATE trigger updateprod
on Products
for update as
begin
declare #qtyonhand int,
#reorder int
if update(QtyonHand)
begin
select #qtyonhand = QtyonHand,#reorder = ReorderAmount from inserted
if #qtyonhand < #reorder
begin
update Reorders set ReorderAmount = #reorder, ReorderDate = getdate()
end
else if #qtyonhand >= #reorder
begin
delete from reorders where ProductID = ProductID
end
end
end
I have an issue with a trigger on a mysql database. I have a table such as follows:
id int not null auto_increment (PK)
parent_id int not null,
rank int not null
What I'm trying to do is use a trigger to update the rank to the next highest +10 when they have the same parent_id, but this doesn't seem to be working.
DELIMITER $$
DROP TRIGGER IF EXISTS after_insert $$
create trigger after_insert
after insert on mytable
FOR EACH row
BEGIN
IF EXISTS (SELECT rank FROM mytable WHERE parent_id = new.parent_id AND id != new.id ORDER BY rank DESC LIMIT 1) THEN
UPDATE mytable SET rank = 10
WHERE id = new.id;
ELSE
UPDATE mytable SET rank = 20
WHERE id = new.id;
END IF;
END
$$
I've tried setting the new rank to a variable and calling the update statement using that, and again it didn't work. I even created another table to log what values were being selected and that worked perfectly so I can't quite understand what's going on. Is it a case of, although the trigger is "AFTER INSERT" the insert hasn't actually happened so it can't update the row it's just inserted? Another reason I ask this is, I've even tried updating the rank to different values e.g 1 and 2 depending on which statement it goes to, but it always ends up being 0.
I think you're on the right track with this thought:
Is it a case of, although the trigger is "AFTER INSERT" the insert hasn't actually happened so it can't update the row it's just inserted?
From the FAQ:
B.5.9: Can triggers access tables?
A trigger can access both old and new data in its own table. A trigger can also affect other tables, but it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.
The documentation isn't clear that what you're doing won't work. OTOH, the documentation isn't clear that what you're trying to do will work either.
I think you'd be better off using a BEFORE INSERT trigger and setting NEW.rank in there. Then, the new row would have the right rank value when it is actually inserted into the table rather than patching it after. Also, you'd be able to simplify your existence check to just this:
EXISTS(SELECT rank FROM mytable WHERE parent_id = new.parent_id)
as NEW.id wouldn't have a useful value and the new row wouldn't be in the table anyway; the ORDER BY and LIMIT are also unnecessary as you're just checking if something exists so I took them out.
A BEFORE INSERT trigger seems to match your intent better anyway and that will give you correct data as soon as it is inserted into your table.
If you want the rank to be set +10 more than highest "brother's" rank, you could use:
DELIMITER $$
DROP TRIGGER IF EXISTS whatever $$
create trigger whatever
BEFORE INSERT ON mytable
FOR EACH row
BEGIN
SET NEW.rank = 10 + COALESCE(
( SELECT max(rank)
FROM mytable
WHERE parent_id = NEW.parent_id
), 0 ) ;
END
$$