Update column value of another table in After Insert Trigger - mysql

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

Related

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 ;

SQL can I create an if statement if subquery returns more than 1 row?

Hi I'm making a procedure "AddToCart" I want to check if there is row with the same column values and if there is update it, if not insert a new row. I keep getting subquery returns more than 1 row.
CREATE PROCEDURE AddToCart(thisCustomerID INT, thisOrdersID INT, thisShoeID INT, thisQuantity INT)
BEGIN
DECLARE any_rows_found int;
IF (thisOrdersID IS NULL)
THEN
INSERT INTO orders (Date, CustomerID)
VALUES (CURRENT_DATE, thisCustomerID);
SELECT COUNT(*)
INTO any_rows_found
FROM Shoe_Orders
WHERE OrdersID = thisOrdersID
AND ShoeID = thisShoeID;
IF (any_rows_found > 0)
THEN
UPDATE shoe_orders
SET Quantity = Quantity + thisQuantity
WHERE ShoeID = thisShoeID
AND OrdersID = thisOrdersID;
ELSE
INSERT INTO shoe_orders (ShoeID, OrdersID, Quantity)
VALUES (thisShoeID, (SELECT ID
FROM orders
WHERE CustomerID = thisCustomerID
AND Date = CURRENT_DATE), thisQuantity);
END IF;
END IF;
END //

MySQL 1:10 fixed relationship. How to implement it at database level?

Is it possible to implement a 1:N relationship that has 10 rows of the many referencing 1 row from the one table at most?
// ID int
INSERT INTO one VALUES (1);
// ...
INSERT INTO one VALUES (25);
//ID int, one_id int
INSERT INTO many VALUES (1,1);
// ...
INSERT INTO many VALUES (1,10);
INSERT INTO many VALUES (1,11); // ERROR!
INSERT INTO many VALUES (2,11); // working
// ...
INSERT INTO many VALUES (2,20); // working
INSERT INTO many VALUES (2,21); // ERROR!
You can do this with a trigger:
create trigger trg_mytable_max10 before insert on mytable
for each row
begin
declare cnt int;
set cnt = (select count(*) from mytable where col1 = new.col1);
if cnt = 10 then
signal sqlstate '45000' set message_text = 'only 10 records per col1 allowed';
end if;
end;
http://rextester.com/EORH56497

MySQL Trigger - Where am I going wrong

Can someone tell me where I'm going wrong in creating this trigger in MySQL? Every time I try to create it, it keeps telling me there is an error.
USE `cl11-onestock`;
DELIMITER //
CREATE TRIGGER audit_insert
AFTER INSERT
ON stock_usage FOR EACH ROW
BEGIN
SET uUid = (SELECT UUID());
SET stockUsageId = (SELECT NEW.stock_usage_id);
SET siteId = (SELECT NEW.site_id);
SET date = (SELECT NEW.date);
SET patientName = (SELECT NEW.patient_name);
SET dentistDiscountId = (SELECT NEW.dentist_discount_id);
SET itemId = (SELECT NEW.item_id);
SET quantity = (SELECT NEW.quantity);
SET priceIncDiscount = (SELECT NEW.price_inc_discount);
SET vat = (SELECT NEW.vat);
SET priceIncVat = (SELECT NEW.price_inc_vat);
SET createdAt = (SELECT NEW.created_at);
SET updatedAt = (SELECT NEW.updated_at);
INSERT INTO stock_audit VALUES
(uUid, stockUsageId, siteId, date, patientName, dentistDiscountId, itemId, quantity, priceIncDiscount, vat, priceIncVat, createdAt, updatedAt);
END; //
DELIMITER ;
You need to use the keyword new to access the field values after insert and not like you are doing with select and you can use directly inside the insert query
So the trigger should be as
DELIMITER //
CREATE TRIGGER audit_insert
AFTER INSERT
ON stock_usage FOR EACH ROW
BEGIN
INSERT INTO stock_audit VALUES
(new.UUID, NEW.stock_usage_id, NEW.site_id, NEW.date, NEW.patient_name, NEW.dentist_discount_id, NEW.item_id, NEW.quantity, NEW.price_inc_discount, NEW.vat, NEW.price_inc_vat, NEW.created_at, NEW.updated_at);
END; //
DELIMITER ;

Mysql trigger to insert on two connected tables

I have 3 mysql tables:
user_followers has columns id,user_id
notification has columns id,user_id
notification_object has columns notification_id , type
On insert on user_followers i want to insert
user_id=New.user_id in notification
and then using the id of notification just inserted
notification_object.type = "2" and notification_object.notification_id = just inserted id in notifcication table
now the problem is how can i find the id of notifcation table:
DELIMITER //
CREATE TRIGGER follow_notification AFTER INSERT ON user_friends
FOR EACH ROW
Begin
insert into notification(user_id) values(New.user_id);
insert into notification_object(notification_id,type) values(????,"2");
End
//
if notifications.id is auto-incremented, mysql includes a function last_insert_id() that will return (with caveats) the lastly inserted id.
DELIMITER //
CREATE TRIGGER follow_notification AFTER INSERT ON user_friends
FOR EACH ROW
Begin
declare v_notification_id INT;
insert into notification(user_id) values(New.user_id);
/* set a variable to the last id inserted to the db */
set v_notification_id=(select last_insert_id());
/* use the variable in the next insert */
insert into notification_object(notification_id,type) values(v_notification_id,"2");
End//