Update a second table, using trigger - mysql

I'm trying to create a simple trigger, but, i can't set the media value on prato if the value comes from #total or #sum.
I've already tested to substitute them for "1" or "1+1", to see if i wasn't even updating correctly or the problem was the operation itself.
DELIMITER $$
CREATE
TRIGGER ratings_prato BEFORE INSERT ON ratings
FOR EACH ROW BEGIN
SET #total = #total + 1;
SET #sum = NEW.stars + #sum;
UPDATE prato p SET p.media = #sum/#total WHERE p.id = 1;
END;
$$
DELIMITER ;
Any ideias?

I've completed mislead the FOR EACH ROW on trigger. I thought, every time it was updated, It would run trough all rows. But, instead of it, it executes for each row it was updated, which, make things possible.
This was the last result of my trigger, inserting on ratings, and updating on food(which was prato)
DELIMITER $$
CREATE
TRIGGER inserting_dishes_rating AFTER INSERT ON ratings
FOR EACH ROW BEGIN
IF(NEW.food_id is not null) THEN
SET #media = (SELECT SUM(stars) FROM ratings WHERE food_id = NEW.food_id) / (SELECT COUNT(*) FROM ratings WHERE food_id = NEW.food_id);
      UPDATE foods f SET f.rate = #media WHERE f.id = NEW.food_id;
    ELSE
  SET #media = (SELECT SUM(stars) FROM ratings WHERE restaurant_id = NEW.restaurant_id) / (SELECT COUNT(*) FROM ratings WHERE restaurant_id = NEW.restaurant_id);  
UPDATE restaurants r SET r.rate = #media WHERE r.id = NEW.restaurant_id;
END IF;
END

Related

sql trigger two tables not empty

CREATE TRIGGER bookAvailDelete after delete on Auction
for each row
Begin
if (Select count(OLD.isbn) from Auction a > 0)
update Book b
set available =false
where OLD.isbn = isbn
;
I have two tables, Auction and Book. Auction has isbn key that references Book isbn primary key. Many auctions can point to the same book so I want this trigger to check on every auction delete, to see if it was the last auction of that book isbn. If it is, then it sets the "available" key in Book to false.
Typically, unless there were performance reasons, you'd just calculate this on the fly (instead of storing it) with queries like:
SELECT b.*
, EXISTS(SELECT * FROM Auction a WHERE a.isbn = b.isbn) AS available
FROM Book b
or (my preferred format):
SELECT b.*, (a.isbn IS NOT NULL) AS available
FROM Book b
LEFT JOIN (SELECT DISTINCT isbn FROM Auction) AS a ON b.isbn = a.isbn
;
Assuming available is int:
drop trigger bookAvailDelete;
DELIMITER //
CREATE TRIGGER bookAvailDelete after delete on Auction
for each row begin
if NOT EXISTS(Select * from Auction where isbn = old.isbn)
then
update Book b set b.available = 0 where b.isbn = old.isbn;
end if;
end;
Please compile and test below. Use a variable for the count and put end if at the end too.
delimiter //
CREATE TRIGGER bookAvailDelete after delete on Auction
for each row
Begin
DECLARE updatecount INT;
set updatecount = ( Select count(*) from Auction a where a.isbn = OLD.isbn);
if updatecount > 0 then
update Book b
set b.available =false
where b.isbn = OLD.isbn;
end if;
End;//

set new value depending on another table value trigger

What I am trying is to set a new value depending on the value from another table. This is a BEFORE UPDATE trigger. I need to set a new.amount in "webs" table depending on the value of percent column from table "webTransactions". If percent = 30.00 then new amount must change from whatever to 0.00. What I tried so far but is giving me error:
if new.type=9 and new.referenceId=0 then set new.amount=0.00 where (SELECT * FROM webs s JOIN webTransactions r ON r.webId = s.id WHERE s.percent = 30.00);
Anyone can help to make this trigger run?
Thank you
you can try something like this
UPDATE websTransactions
SET amount= CASE
WHEN type=9 AND referenceId=0 THEN 0.00
ELSE amount
END
WHERE key IN
(SELECT key FROM webs s JOIN webTransactions r ON r.webId = s.id
WHERE s.percent = 30.00)
replace key with the primary key of websTransactions
You might want to to use some more efficient code, triggers are a sort of stored routines so program them that way. Also, it's not neccesary to join the table you're updating in a subquery.
DELIMITER $$
CREATE TRIGGER amount_check BEFORE UPDATE ON webs
FOR EACH ROW
BEGIN
IF NEW.type=9 and NEW.referenceId=0 THEN
SET #percent := (SELECT percent
FROM webTransactions
WHERE webId = OLD.id);
IF #percent = 33.00 THEN
NEW.amount = 0
END IF;
END IF;
END$$
DELIMITER ;

MYSQL multiple Triggers

I have a MYSQL table and two of the fields are called Rate_per_unit and Cost. First I want the field Rate_per_unit to populate itself from another table called SHD_TEACHER then I want the field COST to populate itself also from RATE in SHD_TEACHER and multiplies by UNITS.
I have the following code which is giving me an error:
CREATE TRIGGER RATE_PER_UNIT_1
BEFORE INSERT ON SHD_SCHEDULE
FOR EACH ROW
SET NEW.RATE_PER_UNIT =
(
SELECT RATE
FROM SHD_TEACHER
WHERE TEACHERID = NEW.TEACHER_ID
LIMIT 1
)
SET NEW.COST = (
SELECT RATE
FROM SHD_TEACHER
WHERE TEACHERID = NEW.TEACHER_ID
) * UNITS
Any help please?
thanks
using your syntax, I would expect a delimiter statement and a begin/end block. So, try this:
DELIMITER $$
CREATE TRIGGER RATE_PER_UNIT_1
BEFORE INSERT ON SHD_SCHEDULE
FOR EACH ROW
BEGIN
SET NEW.RATE_PER_UNIT =
(
SELECT RATE
FROM SHD_TEACHER t
WHERE t.TEACHERID = NEW.TEACHER_ID
LIMIT 1
)
SET NEW.COST = (
SELECT t.RATE
FROM SHD_TEACHER t
WHERE t.TEACHERID = NEW.TEACHER_ID
) * NEW.UNITS
END $$
DELIMITER ;
You have a limit 1 in the first subquery, suggesting that there might be multiple matches. If so, you will get a run-time error in the second. Also, UNITS is just hanging out there, all alone. I assumed it is in the NEW record.
Here is another way to write this:
DELIMITER $$
CREATE TRIGGER RATE_PER_UNIT_1
BEFORE INSERT ON SHD_SCHEDULE
FOR EACH ROW
BEGIN
SELECT NEW.RATE_PER_UNIT := t.RATE, NEW.COST := t.RATE * NEW.UNITS
FROM (SELECT t.*
FROM SHD_TEACHER t
WHERE t.TEACHERID = NEW.TEACHER_ID
LIMIT 1
) t
END $$
DELIMITER ;

Help on removing the aliases from a MySQL trigger

my question is too easy (I guess), below is an example of trigger that I am trying to remove the aliases. I don't know what I am doing wrong I just can't get it right.
DELIMITER #
CREATE TRIGGER StartOfShift BEFORE INSERT ON shift
FOR EACH ROW
BEGIN
IF(NEW.CashierCode NOT IN ( SELECT w.EmployeeID FROM WorksOn as w
JOIN shop AS s ON w.ShopID = s.ShopID
JOIN CashMachineCode AS c ON s.ShopID = c.ShopID
WHERE c.CashMachineCode = NEW.CashMachineCode ))
THEN SET NEW.CashierCode = NULL;
END IF;
END;
The following should be what you are looking for:
DELIMITER #
CREATE TRIGGER StartOfShift BEFORE INSERT ON shift
FOR EACH ROW
BEGIN
IF(NEW.CashierCode NOT IN (
SELECT WorksOn.EmployeeID FROM WorksOn
JOIN shop ON WorksOn.ShopID = shop.ShopID
JOIN CashMachineCode ON shop.ShopID = CashMachineCode.ShopID
WHERE CashMachineCode.CashMachineCode = NEW.CashMachineCode )
) THEN
SET NEW.CashierCode = NULL;
END IF;
END#
DELIMITER ;

Finding min and max value of the table in a constant time

I have a table which contains relative large data,
so that it takes too long for the statements below:
SELECT MIN(column) FROM table WHERE ...
SELECT MAX(column) FROM table WHERE ...
I tried index the column, but the performance still does not suffice my need.
I also thought of caching min and max value in another table by using trigger or event.
But my MySQL version is 5.0.51a which requires SUPER privilege for trigger and does not support event.
It is IMPOSSIBLE for me to have SUPER privilege or to upgrade MySQL.
(If possible, then no need to ask!)
How to solve this problem just inside MySQL?
That is, without the help of OS.
If your column is indexed, you should find min(column) near instantly, because that is the first value MySQL will find.
Same goes for max(column) on an indexed column.
If you cannot add an index for some reason the following triggers will cache the MIN and MAX value in a separate table.
Note that TRUE = 1 and FALSE = 0.
DELIMITER $$
CREATE TRIGGER ai_table1_each AFTER INSERT ON table1 FOR EACH ROW
BEGIN
UPDATE db_info i
SET i.minimum = LEAST(i.minimum, NEW.col)
,i.maximum = GREATEST(i.maximum, NEW.col)
,i.min_count = (i.min_count * (new.col < i.minumum))
+ (i.minimum = new.col) + (i.minimum < new.col)
,i.max_count = (i.max_count * (new.col > i.maximum))
+ (i.maximum = new.col) + (new.col > i.maximum)
WHERE i.tablename = 'table1';
END $$
CREATE TRIGGER ad_table1_each AFTER DELETE ON table1 FOR EACH ROW
BEGIN
DECLARE new_min_count INTEGER;
DECLARE new_max_count INTEGER;
UPDATE db_info i
SET i.min_count = i.min_count - (i.minimum = old.col)
,i.max_count = i.max_count - (i.maximum = old.col)
WHERE i.tablename = 'table1';
SELECT i.min_count INTO new_min_count, i.max_count INTO new_max_count
FROM db_info i
WHERE i.tablename = 'table1';
IF new_max_count = 0 THEN
UPDATE db_info i
CROSS JOIN (SELECT MAX(col) as new_max FROM table1) m
SET i.max_count = 1
,i.maximum = m.new_max;
END IF;
IF new_min_count = 0 THEN
UPDATE db_info i
CROSS JOIN (SELECT MIN(col) as new_min FROM table1) m
SET i.min_count = 1
,i.minimum = m.new_min;
END IF;
END $$
DELIMITER ;
The after update trigger will be some mix of the insert and delete triggers.