Triggers - How to change another column when one is updated - MySQL - mysql

I have been given a use case where an user needs to update a certain TIME field if other of the same type changes.
I have been given two columns
horario_arribo (TIME)
horario_salida (TIME)
Now, what I need to do is the followin
Make a trigger so when I change for example horario_arribo, horario_salida is the same TIME as horario_arribo minus 1 hour, and the same if I update horario_salida , make horario_arribo plus 1 hour.
I have been thinking how to do it, first check if the value trying to be updated is horario_salida, then I just add 1 hour to horario_arribo, or if I'm updating horario_arribo, to the same to horario_salida but minus 1 hour.
DELIMITER //
CREATE TRIGGER modificar_horarioruta AFTER
UPDATE ON ruta
FOR EACH ROW
BEGIN
IF(new.horario_salida) THEN
SET AddTime(old.horario_arribo, '00:60:00')
ELSE
SET AddTime(old.horario_salida, Here I dont know how to minus 1 hour to that)
END IF;
END //
DELIMITER ;
This is the data I have
So , in short, if I update horario_salida, horario_arribo need to be 1 hour ahead, if I update horario_arribo, horario_salida needs to be 1 hour less.
Thanks

IIUC:
DELIMITER //
CREATE TRIGGER modificar_horarioruta AFTER
UPDATE ON ruta
FOR EACH ROW
BEGIN
IF (NEW.horario_salida) THEN
SET NEW.horario_arribo = OLD.horario_arribo + 1;
ELSE
SET NEW.horario_salida = OLD.horario_salida - 1;
END IF;
END //
DELIMITER ;
Let me know if this is not what you need.

Related

MySQL Trigger with Multiple IF Statements

I am new to this and cant seem to find a situation similar to mine and Im sure the answer is simple.
I have two columns, one is a predefined licenseplate ("licenseplate") and one that will be a user inputted licenseplate ("enterlicenseplate").
I made a third column which will be the sort of error check column and will have its values inputted by a trigger. Basically if the entered license plate is the same as the predefined licenseplate, set that third column to 0, if the entered license plate is null(not inputted anything yet( set that to 1, and if theres values in both and they dont match, set it 2. But i keep getting script errors. Not sure if its my syntax or im going about this all wrong.
I appreciate any help!
CREATE TRIGGER MatchPlateOnUPDATE
BEFORE UPDATE ON wp_wpdatable_3
FOR EACH ROW
BEGIN
IF (NEW.enterlicenseplate is NULL) THEN
UPDATE wp_wpdatatable_3
SET MatchingPlates = 0;
ELSEIF (NEW.enterlicensplate = New.licenseplate) THEN
UPDATE wp_Wpdatatable_3
SET MatchingPlates = 1;
ELSE UPDATE wp_Wpdatatable_3
SET MatchingPlates = 2;
END
Your problem with the if statement is that you are missing closing end if;.
But there is more: a trigger cannot action the table it was fired upon - and even if it could, then your query would basically update all rows in the table, since your updates have no where clause.
Here, you just need to modify the value of column matchingPlates in the record that is about to be inserted:
delimiter //
create trigger matchplateonupdate
before update on wp_wpdatable_3
for each row
begin
if new.enterlicenseplate is null then
set new.matchingplates = 0;
elseif new.enterlicensplate = new.licenseplate then
set new.matchingplates = 1;
else
set new.matchingplates = 2;
end if;
end;
//
delimiter ;

How can I make SQL not execute the query if the field goes negative?

I have something like this:
UPDATE users SET credits=credits-1000 WHERE id=1
How do I make this fail if credits goes negative? I want to avoid having to query the database twice just to check for that. I need it to FAIL/return false if it goes negative, not set the credits to zero.
What about adding the condition ?
UPDATE users SET credits=credits-1000 WHERE id=1 AND credits > 1000
I think you have to use stored procedure for this purpose. For example
CREATE procedure UpdateUserCredit
#user_id INT,
#credits INT,
#op_status BIT OUTPUT
AS
BEGIN
SET #op_status = 0
UPDATE Users
SET credits = credits - #credits
WHERE id = #user_id
AND credits - #credits > 0
IF ROW_COUNT() = 0
RETURN
ELSE
SET #op_status = 1
END
This stored procedure will return 0 in variable #op_status if current credits + #credits for #user_id would be less zero.
DELIMITER $$
CREATE TRIGGER users_bu BEFORE UPDATE ON users FOR EACH ROW
BEGIN
IF NEW.credits != OLD.credits AND NEW.credits < 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'negative balances are not supported';
END IF;
END $$
DELIMITER ;
Before the update is written to a row in the table, the new (replacement) value for credits is checked for negative values if that value has been changed by this update. If it changed, and is now negative, deny the update by throwing an exception. Requires MySQL Server 5.5 or later as written, but can be made to work with 5.1 or 5.0 with some modifications.
Note that FOR EACH ROW doesn't mean the whole table, it means that each row affected by the update is evaluated individually by this code, which will of course typically be just one row.

How to store select results in mysql?

In mysql, I have a trigger which checks for collisions, and updates the hp value of rows that have a collision. I also set a boolean value of the projectile to be true to mean that it should be deleted later. But I seem to do something twice that I would rather done once.
DELIMITER //
CREATE TRIGGER checkcollision2 BEFORE UPDATE ON projectiles
FOR EACH ROW
BEGIN
SET #unit_size:=25;
IF (SELECT count(*) FROM players WHERE wolf=1 AND NEW.x>=x AND NEW.x<=x+#unit_size AND NEW.y>=y AND NEW.y<=y+#unit_size)>0 THEN
SET NEW.deleted=1;
UPDATE players SET hp=hp-NEW.dmg WHERE wolf=1 AND NEW.x>=x AND NEW.x<=x+#unit_size AND NEW.y>=y AND NEW.y<=y+#unit_size;
END IF;
END;//
DELIMITER ;
In the above, I do a select which gives me the number of rows that have a collision. Then below I do the same query because I want to update those same rows. I could have just done the update, but I only want to do the SET NEW.deleted=1; if there was at least 1 row affected. Im not sure how to do that if I only keep the update statement.
Does anyone know of a batter way of doing this?
Thanks
If you want to set the NEW.deleted value based on the number of rows affected on update then you can use ROW_COUNT() to check the number of rows affected.
Example:
DELIMITER //
CREATE TRIGGER checkcollision2 BEFORE UPDATE ON projectiles
FOR EACH ROW
BEGIN
SET custom_unit_size := 25;
UPDATE players
SET hp = hp - NEW.dmg
WHERE wolf = 1
AND NEW.x >= x
AND NEW.x <= x + custom_unit_size
AND NEW.y >= y
AND NEW.y <= y + custom_unit_size;
IF ROW_COUNT() > 0 THEN
SET NEW.deleted = 1;
END IF;
END;
//
DELIMITER ;
Refer to:
ROW_COUNT()
returns the number of rows changed, deleted, or inserted by the last statement if it was an UPDATE, DELETE, or INSERT. For other statements, the value may not be meaningful.

MySQL nested Conditional in Update Trigger

I am trying to figure out a conditional trigger for an update to a MySQL table.
The issue is that the update trigger fires off even when the data being entered is the same as the data that was already there. So if I have a column with a row:value set up like this plus_votes:2 if I update with UPDATE votes SET plus_votes = 2; even though nothing has really changed the UPDATE trigger still gets fired off. So to prevent all of this I want to add a conditional clause to my trigger like this
BEGIN
IF NEW.vote_value <> OLD.vote_value THEN
UPDATE my_other_table
SET plus_votes =
CASE NEW.vote_value WHEN '1'
THEN plus_votes + 1
ELSE plus_votes
END,
minus_votes =
CASE NEW.vote_value WHEN '1'
THEN minus_votes
ELSE minus_votes +1
END
WHERE my_other_table.id=NEW.votes_join_id;
END
END
the second half of the issue is that I have CASE condition inside the IF statement.
Can someone help on this issiu and show how to do nested conditionals inside a TRIGGER?
much appreciated
although the syntax you have posted is completely wrong, I have figured out what you want try this ( not tested )
DROP TRIGGER IF EXISTS upd_vote;
DELIMITER $$
CREATE TRIGGER upd_vote AFTER UPDATE ON `my_other_table`
FOR EACH ROW BEGIN
IF NEW.vote_value <> OLD.vote_value THEN
SET
NEW.plus_votes = IF(NEW.vote_value=1,OLD.plus_votes+1,OLD.plus_votes),
NEW.minus_votes = IF(NEW.vote_value=1,OLD.minus_votes,OLD.minus_votes +1 )
END IF;
END$$
DELIMITER ;

How to fix this MySQL trigger?

I'm trying to get this trigger to work:
CREATE TRIGGER Transaction_insert BEFORE INSERT ON Transaction
FOR EACH ROW WHERE Number = NEW.AccountNumber
IF Account.CreditBalance + NEW.Amount < Account.CreditLimit THEN
UPDATE Account SET CreditBalance = CreditBalance + NEW.Amount where Number = NEW.AccountNumber;
ELSE
SET NEW.Valid = 0
END IF;
This is the error I get from myPHPAdmin.
Your IF needs to be a full SELECT to reference another table (Account)
IF EXISTS (SELECT * FROM `Account` A
WHERE A.CreditBalance + NEW.Amount < A.CreditLimit AND
A.Number = NEW.AccountNumber) THEN
UPDATE ...
Edit: this was on your 2nd duplicate answer
In this case, remove the WHERE after FOR EACH ROW
Updated Answer
This is what I think you want, assuming that Account to Transaction is a 1:N relationship keyed on Number/AccountNumber:
DELIMITER //
-- Assumptions:
-- 1. Transaction.AccountNumber is F.K. REFERENCES Account(Number)
-- 2. Account.Number is UNIQUE
--
CREATE TRIGGER trg_bi_transaction BEFORE INSERT ON Transaction
FOR EACH ROW
BEGIN
-- Adjust account balance (if permitted)
--
UPDATE Account
SET CreditBalance = CreditBalance + NEW.Amount
WHERE Number = NEW.AccountNumber
AND
(CreditBalance + NEW.Amount) < CreditLimit;
-- Was the adjustment valid/permitted?
--
SET NEW.Valid = (ROW_COUNT() = 1);
END //
DELIMITER ;
That trigger will attempt to UPDATE the proper Account for any given Transaction if the CreditLimit permits. The Valid field will be set to 1 if the UPDATE succeeded, and 0 if it did not.
Original Answer
MySQL triggers do not support trigger-level WHERE clauses. Move the Number/NEW.AccountNumber check inside the trigger body.