MYSQL trigger to update or insert based on if statements - mysql

I have two tables, tbl_stock and tbl_stockEntry, those two tables are identical.
They have these fields:
warehouse
cultivar
variety
quantity
when an entry is entered in to the tbl_stockEntry table I would like it to either update the matching entry in the tbl_stock table or create a new entry if there is no matching entry.
But I need it to match 3 fields, warehouse, cultivar and variety.
This is my trigger to create the entry, but I can't seem to get it to insert a record if none is found.
BEGIN
UPDATE tbl_stock
SET quantity = quantity + NEW.quantity
WHERE vegetableCultivar = NEW.vegetableCultivar
AND warehouse = NEW.warehouse;
END
I have tried this and but it doesnt work:
BEGIN
UPDATE tbl_stock
SET quantity = quantity + NEW.quantity
WHERE vegetableCultivar = NEW.vegetableCultivar
AND warehouse = NEW.warehouse;
if sql%rowcount = 0 then
-- nothing was updated, so the record doesn't exist, insert it.
insert into tbl_stock (warehouse, vegetableCultivar, vegetableVariety, quantity)
values (NEW.warehouse, NEW.vegetableCultivar, NEW.vegetableVariety, NEW.quantity);
end if;
END
If anyone knows how I could accomplish this I would really appreciate some assistance.

Ok this is working:
BEGIN
UPDATE tbl_stock
SET quantity = quantity + NEW.quantity
WHERE vegetableCultivar = NEW.vegetableCultivar
AND warehouse = NEW.warehouse;
IF ROW_COUNT() = 0 THEN
INSERT INTO tbl_stock (warehouse, vegetableCultivar, vegetableVariety, quantity)
values (NEW.warehouse, NEW.vegetableCultivar, NEW.vegetableVariety, NEW.quantity);
end if;
END

Related

Update column value of another table in After Insert Trigger

I have two different tables: OrderItem and Item. Both tables have a column named "pieces". In the case of table OrderItem the pieces are the amount of each item in the OrderItem's list and in the table Item the pieces represent the remaining pieces of a product (in a warehouse for example).
So I am building an after insert trigger that will update the pieces in Items after an insert is done in OderItem
delimiter //
create trigger TrgItemPieces
after insert on OrderItem
for each row
begin
declare PiecesNew int;
select a.pieces - new.Pieces into PiecesNew from Item a where a.ID = new.ItemId;
update Item set pieces = PiecesNew where id = new.ItemId;
end//
delimiter ;
But when I do an insert
INSERT INTO OrderItem VALUES ([OrderID],[ItemID],Pieces); I get the following error:Error Code: 1442. Can't update table 'Item' in stored function/trigger because it is already used by statement which invoked this stored function/trigger..
What am I doing wrong and how to fix it?
EDIT:
I get the ItemID by doing a select in the insert statement INSERT INTO ORDERITEM VALUES(1,(select i.ID from Item where i.Name = 'Item1'),5);
It's a safety measure from MySql to avoid deadlocks.
But you can avoid it by not directly selecting from the table that will be updated via the trigger.
For example by using variables.
CREATE TRIGGER TrgOrderItemAftIns
AFTER INSERT ON ORDERITEM
FOR EACH ROW
BEGIN
INSERT INTO DEBUG_TABLE (MSG) VALUES (CONCAT('TrgOrderItemAftIns: ', NEW.ITEMID,',',NEW.PIECES));
UPDATE ITEM SET PIECES = PIECES - NEW.PIECES WHERE ID = NEW.ITEMID;
END;
SET #OrderID = (select ID from TabOrder where Name = 'Order 1');
SET #ItemID = (select ID from ITEM where Name = 'Item1');
INSERT INTO ORDERITEM (OrderID, ITEMID, PIECES) VALUES
(#OrderID, #ItemID, 5);
SET #OrderID = (select ID from TabOrder where Name = 'Order 1');
SET #ItemID = (select ID from ITEM where Name = 'Item2');
INSERT INTO ORDERITEM (OrderID, ITEMID, PIECES) VALUES
(#OrderID, #ItemID, 1);
SET #OrderID = (select ID from TabOrder where Name = 'Order 2');
SET #ItemID = (select ID from ITEM where Name = 'Item1');
INSERT INTO ORDERITEM (OrderID, ITEMID, PIECES) VALUES
(#OrderID, #ItemID, 3);
Demo on db<>fiddle here

How do i create an INSERT trigger that based on a condition, either updates or inserts into another table?

I'm trying to create a trigger in phpmyadmin and I have 2 tables, Items and Inventory. This is for a Library Database. When i insert a new item, if the items isbn already exists in the inventory, i want to add to the totalCopies of that item in the inventory. If not, i want it to insert into inventory a new row with the new items isbn. This is my first time using triggers and I'm getting syntax errors. This is what i have right now.
BEGIN
IF ((SELECT COUNT(*) FROM inventory WHERE inventory.isbn = NEW.isbn) > 0) THEN
(
UPDATE inventory
SET inventory.totalCopies = inventory.totalCopies + 1
WHERE inventory.isbn = NEW.isbn
SET inventory.totalAvailable = inventory.totalAvailable + 1
WHERE inventory.isbn = NEW.isbn
)
ELSE
INSERT INTO inventory VALUES( , NEW.isbn, 1, 1, 0)
END
The inventory columns are : inventoryID (PrimaryKey)(autoincrement), isbn, totalCopies, totalAvailable, totalCheckedOut.
I assume for this trigger that inventory id is an auto_increment value,
or else the insert gives an error.
the UPDATE query can be a little simplifoed
DELIMITER $$
CREATE TRIGGER insorup
AFTER INSERT
ON ORDERS FOR EACH ROW
BEGIN
IF (EXISTS(SELECT 1 FROM inventory WHERE inventory.isbn = NEW.isbn) ) THEN
UPDATE inventory
SET inventory.totalCopies = inventory.totalCopies + 1 ,
inventory.totalAvailable = inventory.totalAvailable + 1
WHERE inventory.isbn = NEW.isbn;
ELSE
INSERT INTO inventory VALUES ( NEW.isbn, 1, 1, 0);
END IF;
END$$
DELIMITER ;
as you see in the comment, Shadow pointed out that it is also possible to reduce the inner Part. When you have the column ISBN declared as UNIQUE
DELIMITER $$
CREATE TRIGGER insorup
AFTER INSERT
ON ORDERS FOR EACH ROW
BEGIN
INSERT INTO
inventory VALUES ( NEW.isbn, 1, 1, 0)
ON DUPLICATE KEY UPDATE inventory.totalCopies = inventory.totalCopies + 1 ,
inventory.totalAvailable = inventory.totalAvailable + 1;
END$$
DELIMITER ;

Updating a table entry tells me the table does not exist in a procedure

I'm trying to create a stored procedure that attempts to update an order if the stock is sufficient, however when the update is attempted (but only if it is done within the procedure) I'm given the error
"
15:20:05 call plswork(#LatestOrder, 2, 20) Error Code: 1109. Unknown table 'Product' in field list 0.000 sec
"
So far I've attempted to see if there are any mistakes in table names and table keys. I've also tried to do the update outside of the procedure, here it works.
Delimiter ¤
create procedure plswork(
in NewOrder INT,
in ProductID INT,
in PurchaseQuantity INT)
begin
start transaction;
insert into Order_items(Oid, Pid, Quantity)
values (NewOrder, ProductID, PurchaseQuantity);
update Product p
set p.Stock = p.Stock - PurchaseQuantity
where p.Pid = p.ProductID;
if((select Product.Stock
where Pid = ProductID) < 0) then
rollback;
else
commit;
end if;
end ¤
Delimiter ;
INSERT INTO Orders(Cid,Order_date, Order_status)
VALUES (1, '2040-01-31 12:11:00' , "SENT");
select #LatestOrder := max(Oid)
from Orders;
call plswork(#LatestOrder, 2, 20);
What can I do to fix my issue?
I don't think the error is from the UPDATE statement.
I think the error is being thrown with this SQL statement:
select Product.Stock where Pid = ProductID
There's no FROM clause, so qualifying Stock with table name Product is not valid.

Trigger syntax wrong

I'm trying to create a trigger to give "SumBeforeTaxes(from 'order')" a value.
The "SumBeforeTaxes" is itemQuantity(from 'order_item') x price ('from itemsinstock').
So if one has ordered 3 items at 10 USD each, the "SumBeforeTaxes" would be 3 x 10 (30 in total). Likewise, if one has ordered 3 items at 10 USD each AND 2 items at 15 each, the "SumBeforeTaxes" should be 3x10 + 2x15 (60 in total).
Here's what I've tried so far - but I keep getting syntax errors. I'm also not sure my triggers (despite the syntax errors) are correct.
1st attempt:
CREATE DEFINER = CURRENT_USER TRIGGER `orderdb`.`order_AFTER_INSERT`
AFTER INSERT ON `order_item` FOR EACH ROW
BEGIN
SET getItemPrice = (SELECT Price FROM itemsinstock);
INSERT orderdb.'order'
SET SumBeforeTax = itemQuantity * getItemPrice;
END
2nd attempt:
CREATE DEFINER = CURRENT_USER TRIGGER `orderdb`.`order_AFTER_INSERT`
AFTER INSERT ON `order_item` FOR EACH ROW
BEGIN
SET getItemPrice = (SELECT Price FROM itemsinstock);
INSERT INTO orderdb.'order' (SumBeforeTax) VALUES (new.itemQuantity * getItemPrice);
END
3rd attempt:
CREATE DEFINER = CURRENT_USER TRIGGER `orderdb`.`order_AFTER_INSERT`
AFTER INSERT ON `order_item` FOR EACH ROW
BEGIN
declare getItemPrice DOUBLE;
SET getItemPrice = (SELECT Price FROM itemsinstock WHERE ItemID = new.itemID);
INSERT INTO orderdb.'order'(SumBeforeTax) VALUES (itemQuantity * getItemPrice);
END
Can I get a little help on this one?
order is a reserve word in MySQL and thus you need to escape it like below using backtique for your INSERT statement.
INSERT INTO orderdb.`order`(SumBeforeTax) VALUES (itemQuantity * getItemPrice);
For any syntactical clarification refer Documentation On CREATE TRIGGER Syntax.
You might want to change your code like below in that case using an UPDATE statement rather:
BEGIN
declare getItemPrice DOUBLE;
SELECT Price INTO getItemPrice FROM itemsinstock WHERE ItemID = new.itemID;
UPDATE orderdb.`order` SET SumBeforeTax = new.itemQuantity * getItemPrice
WHERE OrderID = 101;

trigger mysql unknown table

I've been trying to solve this problem. Here is the code:
CREATE TRIGGER some_trigger AFTER UPDATE ON table_a
FOR EACH ROW BEGIN
DECLARE tname VARCHAR(20);
IF (table_a.field_offer=1) THEN
SET tname='table_b';
ELSEIF (table_a.field_offer=0) THEN
SET tname='table_c';
END IF;
IF ((new.field_state = 0)) THEN
UPDATE tname join table_a on tname.ID=table_a.ref_field
SET tname.STOCK = tname.STOCK -1;
ELSEIF ((new.field_state = 1)) THEN
UPDATE tname join table_a on tname.ID=table_a.ref_field
SET tname.STOCK = tname.STOCK +1;
END IF;
END;
I am getting:
Unknown table 'table_a' in field list. Field_offer and field_state can
be null.
I've shown below what was said in the comments to the question:
CREATE TRIGGER some_trigger AFTER UPDATE ON table_a
FOR EACH ROW BEGIN
DECLARE tname VARCHAR(20);
IF (NEW.field_offer=1) THEN
UPDATE `table_b`
SET STOCK = CASE NEW.field_state
WHEN 0 THEN STOCK - 1
WHEN 1 THEN STOCK + 1
ELSE STOCK
END
WHERE ID=NEW.ref_field
;
ELSEIF (NEW.field_offer=0) THEN
UPDATE `table_c`
SET STOCK = CASE NEW.field_state
WHEN 0 THEN STOCK - 1
WHEN 1 THEN STOCK + 1
ELSE STOCK
END
WHERE ID=NEW.ref_field
;
END IF;
...
Note that I changed the updates from UPDATE ... JOIN as MySQL does not allow you to change the data of the triggered table; while you were not actually updating table_a, the JOIN could have been enough for MySQL to have objected... that and the joins would've updated every row in table_b/c that had a match in table_a, not just table_a rows related to the values in or row of the trigger.