Using join in update command in trigger - mysql

I have 3 tables
'stockMedicina' (farmaciaID,seriemedicina,stock)
'Factura' (farmaciaid,facturaid)
'DetalleFactura' (facturaid,seriemedicina,cantidad)
and i want to update the inventory of stockMedicina which is an int named stock when i insert a new value to detalleFactura. So when i insert a new value in detalleFactura i want to update the inventory of the farmaciaid which is on the factura table to decrease the amount of stock. I have this code but it doesn't work, and i don't know what to do now. :(
DELIMITER $$;
CREATE TRIGGER diminuirStock
AFTER INSERT ON detalleFactura
FOR EACH ROW
BEGIN
UPDATE stockmedicina sm
INNER JOIN factura fa ON sm.farmaciaid = fa.farmacia
INNER JOIN detalleFactura df ON sm.seriemedicina = df.seriemedicina AND fa.facturaID=df.facturaID
SET sm.stock = sm.stock - NEW.cantidad
WHERE sm.FarmaciaID = fa.Farmacia and sm.seriemedicina=NEW.facturaID
END$$
DELIMITER ;
Any thought or help about it would be really helpful :c

Some of your columns have the false column name
Schema (MySQL v8.0)
CREATE TABLE stockMedicina (farmaciaID INT,seriemedicina INT ,stock INT);
INSERT INTO stockMedicina VALUES (1,1,10);
CREATE TABLE Factura (farmaciaid INT, faturaid INT);
INSERT INTO Factura VALUES (1,1);
CREATE TABLE DetalleFactura (facturaid INT ,seriemedicina INT ,cantidad INT);
DELIMITER $$
CREATE TRIGGER diminuirStock
AFTER INSERT ON DetalleFactura
FOR EACH ROW
BEGIN
UPDATE stockMedicina sm
INNER JOIN Factura fa ON sm.farmaciaID = fa.farmaciaid
INNER JOIN DetalleFactura df ON sm.seriemedicina = df.seriemedicina AND fa.faturaid=df.facturaID
SET sm.stock = sm.stock - NEW.cantidad
WHERE sm.FarmaciaID = fa.farmaciaid and sm.seriemedicina=NEW.facturaid;
END$$
DELIMITER ;
INSERT INTO DetalleFactura VALUES (1,1,2)
Query #1
SELECT * FROM stockMedicina;
| farmaciaID | seriemedicina | stock |
| ---------- | ------------- | ----- |
| 1 | 1 | 8 |
View on DB Fiddle

Related

Mysql trigger is not updating record

I have two tables "Products" and "stocks". Products table will have all the products. In stock table, I save stock of product as a new entry each time.
I have two type of products. Product of "1" type will have stock as a number and product of "0" type will have stock as weight. Therefore, in products table I have created two columns "stock_weight (to keep total weight entered in stock table)" and "pieces (to keep total quantity entered in stock table)".
For this I have created a trigger on stock table that will execute to update total weight or quantity(pieces) in products table whenever I will insert new record into this table. Below is the code of trigger:
BEGIN
DECLARE product_type tinyint default 0;
SET product_type = (Select product_type from products where id = NEW.product_id);
IF (product_type = 0) THEN
UPDATE products set stock_weight = stock_weight + NEW.net_weight where id = NEW.product_id;
ELSE
UPDATE products set stock_pieces = stock_pieces + NEW.pieces where id = NEW.product_id;
END IF;
END
But after inserting new record in stock table for any product, nothing is updating in product table. I have debugged trigger and trigger is executing but nothing is updating in product table.
Can someone please tell me what I am missing and what thing I am doing wrong?
Don't give variables the same name as columns and anticipate nulls
DROP TABLE IF EXISTS PRODUCTS,STOCKS;
create table products(id int,product_type int,stock_weight int,stock_pieces int);
create table stocks(product_id int,net_weight int,pieces int);
drop trigger if exists t;
delimiter $$
create trigger t after insert on stocks
for each row
BEGIN
DECLARE vproduct_type tinyint default 0;
SET vproduct_type = (Select product_type from products where id = NEW.product_id);
IF (vproduct_type = 0) THEN
UPDATE products set stock_weight = coalesce(stock_weight,0) + NEW.net_weight where id = NEW.product_id;
ELSE
UPDATE products set stock_pieces = coalesce(stock_pieces,0) + NEW.pieces where id = NEW.product_id;
END IF;
END $$
delimiter ;
insert into products values(1,1,null,null),(2,0,null,null);
insert into stocks values(1,null,10),(2,10,null);
select * from products;
+------+--------------+--------------+--------------+
| id | product_type | stock_weight | stock_pieces |
+------+--------------+--------------+--------------+
| 1 | 1 | NULL | 10 |
| 2 | 0 | 10 | NULL |
+------+--------------+--------------+--------------+
2 rows in set (0.001 sec)

How to make triggers for delete and adding with if statement MySQL?

have two table's Queue (appointment_id, actual_time) Queue_Summary (date, doctor_id, num_of_patients)
The first is all the queues there are and the second is how many queues for each doctor on a certain date. I need to build a trigger that updates the num_of_patients, every time in Queue that a queue is added I need to add to a doctor num_of_patients on that date. Also when removing.
I have just counted the number of queues given a doctor_id and date, made it into two triggers.
But the only problem I have is where do I place the if statement that checks if this date is on Queue_Summary and if not adds it.
(P.S - Im not 100% on thoes also as my database is a bit off and does tons of problems, if there are any problem in thoes statments I'll be more them happy to know)
delimiter //
CREATE TRIGGER update_queue_summary
AFTER DELETE ON queue
FOR EACH ROW
BEGIN
update queue_summary as qs set num_of_patient = (
select count(appointment_id)
from queue as q join appointment as a on appointment_id
where a.doctor_id=qs.doctor_id and date(qs.actual_time)=date(qs.date())
group by appointment_id
) where doctor_id=qs.doctor_id and date(qs.actual_time)=date(qs.date());
END;//
delimiter ;
delimiter //
CREATE TRIGGER update_queue_summary
AFTER insert ON queue
FOR EACH ROW
BEGIN
update queue_summary as qs set num_of_patient = (
select count(appointment_id)
from queue as q join appointment as a on appointment_id
where a.doctor_id=qs.doctor_id and date(qs.actual_time)=date(qs.date())
group by appointment_id
) where doctor_id=qs.doctor_id and date(qs.actual_time)=date(qs.date());
END;//
delimiter ;
You should carry out an existence test in your trigger. For example
drop table if exists queue,queue_summary;
create table queue (appointment_id int auto_increment primary key, doctor_id int,actual_time datetime);
create table Queue_Summary (date date, doctor_id int, num_of_patients int);
delimiter $$
create trigger ut after insert on queue
for each row
begin
if not exists (select 1 from queue_summary where date = date(new.actual_time) and doctor_id = new.doctor_id) then
insert into queue_summary values(date(new.actual_time),new.doctor_id,1);
else
update queue_summary
set num_of_patients = num_of_patients + 1
where date = date(new.actual_time) and doctor_id = new.doctor_id;
end if;
end $$
delimiter ;
insert into queue (doctor_id,actual_time) values(1,'2020-05-03 09:00'),(1,'2020-05-03 09:30');
select * from queue;
select * from queue_summary;
MariaDB [sandbox]> select * from queue;
+----------------+-----------+---------------------+
| appointment_id | doctor_id | actual_time |
+----------------+-----------+---------------------+
| 1 | 1 | 2020-05-03 09:00:00 |
| 2 | 1 | 2020-05-03 09:30:00 |
+----------------+-----------+---------------------+
2 rows in set (0.001 sec)
MariaDB [sandbox]> select * from queue_summary;
+------------+-----------+-----------------+
| date | doctor_id | num_of_patients |
+------------+-----------+-----------------+
| 2020-05-03 | 1 | 2 |
+------------+-----------+-----------------+
1 row in set (0.001 sec)
And a delete trigger is similar but simpler
delimiter $$
create trigger dt after delete on queue
for each row
begin
if exists (select 1 from queue_summary where date = date(OLD.actual_time) and doctor_id = old.doctor_id) then
update queue_summary
set num_of_patients = num_of_patients - 1
where date = date(old.actual_time) and doctor_id = old.doctor_id;
end if;
end $$
delimiter ;
The existence check is entirely cosmetic since a delete won't complain if there is nothing to delete.

TRIGGER with insert partial field

2 tables
tb_product :
product_id,
product_size_values
tb_product_category :
product_id ,
category_id
product_size_values contains '41,42,46' or '44,45,46,47' or any values from 42 to 48 with coma separator ....
and the trigger
CREATE TRIGGER trg_product_size AFTER UPDATE ON tb_product
FOR EACH ROW
BEGIN
IF (NEW.product_size_values != OLD.product_size_values) THEN
INSERT INTO tb_product_category (product_id, product_size_values)
VALUES (NEW.product_id, 42) WHERE NEW.product_size_values LIKE '%42%'
;
INSERT INTO tb_product_category (product_id, product_size_values)
VALUES (NEW.product_id, 43) WHERE NEW.product_size_values LIKE '%43%'
;
END IF;
END //
of course the WHERE NEW.product_size_values LIKE does not work
my normal query to do that actually (without trigger ) is
insert into tb_product_category (product_id,category_id)
select product_id,42
from tb_product
where product_size_values like '%42%' ;
insert into tb_product_category (product_id,category_id)
select product_id,43
from tb_product
where product_size_values like '%43%' ;
and NO the comma separated field cannot be changed
thanks for helping
I guess the problem is that you cannot use a like test in a conditional statement and you cannot use a where clause with values and an insert select seems wasteful. You may be able to ditch the like clause and use and instr or locate to check values for example
drop table if exists tb_product,tb_product_category;
create table tb_product
(product_id int,
product_size_values varchar(20));
insert into tb_product values
(1,'42');
create table tb_product_category
(product_id int,
category_id int);
drop trigger if exists trg_product_size;
delimiter $$
CREATE TRIGGER trg_product_size AFTER UPDATE ON tb_product
FOR EACH ROW
BEGIN
IF (NEW.product_size_values != OLD.product_size_values) THEN
if instr(NEW.product_size_values,42) > 0 then
INSERT INTO tb_product_category (product_id, category_id) values (new.product_id,42);
end if;
if INSTR(NEW.product_size_values,43) > 0 then
INSERT INTO tb_product_category (product_id, category_id) values (new.product_id,43);
end if;
END IF;
END $$
delimiter ;
select product_size_values from tb_product;
update tb_product
set product_size_values = '42,43' where product_id = 1;
select * from tb_product_Category;
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1 | 42 |
| 1 | 43 |
+------------+-------------+
Works as coded. You may wish to change the insert logic to check for existence before inserting to avoid duplicates.

WHILE Loop with insert not working as expected

I am try to find all child and sub-child of a given parent, but not getting desired output if I use WHILE loop. Surprisingly, if I execute the scripts manually, it works as expected. Please have a look at below script.
DROP TABLE IF EXISTS test;
CREATE TABLE test (id INT, parent_id INT);
INSERT INTO test VALUES (1,NULL);
INSERT INTO test VALUES (2,1);
INSERT INTO test VALUES (3,2);
INSERT INTO test VALUES (4,2);
INSERT INTO test VALUES (5,3);
INSERT INTO test VALUES (6,4);
INSERT INTO test VALUES (7,2);
INSERT INTO test VALUES (8,4);
INSERT INTO test VALUES (9,1);
INSERT INTO test VALUES (10,1);
COMMIT;
DELIMITER $$
USE `test`$$
DROP PROCEDURE IF EXISTS `get_parent_child_hierarchy`$$
CREATE PROCEDURE `get_parent_child_hierarchy`(Parent_ID INT)
BEGIN
DECLARE `rowcount` INT DEFAULT 1;
DROP TABLE IF EXISTS Temp;
CREATE TABLE Temp(ParentID INT, ChildID INT, Stage INT);
INSERT INTO Temp(ParentID, ChildID, Stage)
SELECT Parent_ID, Parent_ID, 2;
WHILE rowcount > 0 DO
UPDATE Temp
SET Stage = 1
WHERE Stage = 2;
COMMIT;
INSERT INTO Temp(ParentID, ChildID, Stage)
SELECT Parent_ID, id, 2
FROM Test T
WHERE Parent_id IN (SELECT ChildID
FROM Temp
WHERE Stage = 1
AND Temp.ChildID <> T.id);
UPDATE Temp
SET Stage = 0
WHERE Stage = 1;
COMMIT;
SET rowcount = (SELECT COUNT(ChildID)
FROM Temp
WHERE Stage = 2);
END WHILE;
SELECT *
FROM Temp
WHERE Parent_ID <> ChildID;
DROP TABLE IF EXISTS Temp;
END$$
DELIMITER ;
Input: 2
Expected Output:
ParentID | ChildID | Stage
---------|---------|------
2 | 3 | 0
2 | 4 | 0
2 | 5 | 0
2 | 6 | 0
2 | 7 | 0
2 | 8 | 0
But unfortunately, when the run the script using WHILE loop, I get all the rows in the input.
Any help is appreciated.
I agree this is moreover specific problem than issue with technical stuff. But I wonder if there is any issue with MySQL, when you use WHILE loop and INSERT.
You defined input parameter's name as Parent_ID which is a column in table test, this is reason that you did not get what you expected.
Try following;)
CREATE PROCEDURE `get_parent_child_hierarchy`(pid INT)
BEGIN
DECLARE `rowcount` INT DEFAULT 1;
DROP TABLE IF EXISTS Temp;
CREATE TABLE Temp(ParentID INT, ChildID INT, Stage INT);
INSERT INTO Temp(ParentID, ChildID, Stage)
SELECT pid, pid, 2;
WHILE rowcount > 0 DO
UPDATE Temp
SET Stage = 1
WHERE Stage = 2;
COMMIT;
INSERT INTO Temp(ParentID, ChildID, Stage)
SELECT pid, id, 2
FROM test T
WHERE parent_id IN (SELECT ChildID
FROM Temp
WHERE Stage = 1
AND Temp.ChildID <> T.id);
UPDATE Temp
SET Stage = 0
WHERE Stage = 1;
COMMIT;
SET rowcount = (SELECT COUNT(ChildID)
FROM Temp
WHERE Stage = 2);
END WHILE;
SELECT *
FROM Temp
WHERE pid <> ChildID;
DROP TABLE IF EXISTS Temp;
END

how to get the updated row from a table when calling a trigger after update

This is my table structure
mysql> select * from product_table;
+----------------+---------------------+
| product_number | product_description |
+----------------+---------------------+
| 1 | product one |
| 2 | product two |
| 3 | product three |
| 9 | product five |
| 10 | product six |
| 11 | product six |
+----------------+---------------------+
I want to say update a row say 9th product number from the table like this
UPDATE product_table SET product_description ="product seven" WHERE product_number=9;
So that in the trigger i can get the corresponding updated product number from the table product_table
I wrote the trigger like this and it got created without any errors.
DELIMITER //
CREATE TRIGGER product_table_update
AFTER UPDATE
ON product_table
FOR EACH ROW
BEGIN
DECLARE l_product_number INT;
set #l_table_name = 'product_table';
set #l_action = 'updation';
SET #l_table_column = 'product_description';
select new.product_number into #l_product_number from product_table;// here is i think where the problem is , i am trying to fetch the updated row to l_product_number
IF (OLD.product_description <> NEW.product_description) THEN
SET #oldval = OLD.product_description;
SET #newval = NEW.product_description;
select concat(#oldval,#newval) into #l_description;
END IF;
INSERT INTO audit_table_test
( table_name,
changed_row_id,
action,
table_column,
change_desciption,
change_time
)
VALUES
( #l_table_name,
#l_product_number,
#l_action,
#l_table_column,
#l_description,
NOW()
);
END; //
DELIMITER ;
then when i tried to update like this
UPDATE product_table SET product_description ="product seven" WHERE product_number=11;
This error is showing
ERROR 1172 (42000): Result consisted of more than one row
I know the problem has to be in this code
select new.product_number into #l_product_number from product_table;// here is i think where the problem is , i am trying to fetch the updated row to l_product_number
Please someone help me to get the update row on calling this trigger
Try:
...
SET #l_table_column = 'product_description';
/*
here is i think where the problem is , i am trying to fetch the
updated row to l_product_number
*/
-- select new.product_number into #l_product_number from product_table;
SET #l_product_number := NEW.product_number;
IF (OLD.product_description <> NEW.product_description) THEN
...