I have a special requirement where I need to automatically update a 'modifiedDate' column's datetime value to NOW(), IF:
Value provided is null
Value provided is the same as what it was before the update
BUT
If value provided is any other date string, then update column with value.
So, I've setup this trigger, but something's now quite right with it:
CREATE TRIGGER `tr_users_updateModDateOnUpdate` BEFORE UPDATE ON `tbl_users`
FOR EACH ROW IF (OLD.date_modified <> NEW.date_modified) THEN
SET NEW.date_modified = IFNULL(NEW.date_modified, NOW());
ELSE
SET NEW.date_modified = NOW();
END IF
I can't see what's wrong with it... , but I'm getting strange behavior when testing with my web application.. So trying to see if the problem is with my trigger, or my php code...
Can anyone tell me if my Trigger code seems okay for my requirements above? Thanks a million!
Pat
Your trigger contains an IF statement, so it needs at BEGIN/END block. Also, the conditions do not seem to do what you want. Finally, you need to set the DELIMITER.
I think that this does what you want:
delimiter //
create trigger tr_users_update_mod_date_on_update
before update on tbl_users
for each row
begin
if new.date_modified is null or old.date_modified = new.date_modified then
set new.date_modified = now();
end if;
end;
//
delimiter ;
Related
Hi I just need help as I am just new to mysql trigger.
I'm trying to create a trigger that if the project id is NULL then it will set it to new value but if someone has manually insert a value then it won't do anything.
I performed this but it ain't working on mysql.
CREATE TRIGGER custom_autonums_pdl BEFORE INSERT ON project_details_logs
FOR each ROW
WHEN (new.projectid IS NULL)
BEGIN
SET new.projectid = getNextCustomSeqPl(year(now()),year(now()));
END//
delimiter ;
If someone can direct me to correct this, appreciate it.
Thank you.
I haven't seen a MariaDb/MySQL trigger that uses the WHEN syntax available in other major RDBMS - you'd need to run the trigger for every insert and conditionally act on the id:
DELIMITER |
CREATE TRIGGER custom_autonums_pdl
BEFORE INSERT ON project_details_logs
FOR each ROW
BEGIN
IF new.projectid IS NULL THEN
SET new.projectid = getNextCustomSeqPl(year(now()),year(now()));
END IF;
END|
DELIMITER ;
Trying to get a trigger to work that refuses to I think it has to be setup as a procedure for it to work which I've never worked with before could anyone tell me how I would go about this? The trigger doesn't show errors when adding but just doesn't do anything
** It now does work apart from changing processed to 0)
UPDATE product
INNER JOIN ebaylinked ON ebaylinked.ebay_ID = product.eBay_ID
SET product.product_stock = product.product_stock - NEW.QuantitySold,NEW.Processed=0
WHERE product.eBay_ID = NEW.ebay_ID and NEW.Processed = 1
First of all, find a more descriptive name for your trigger ;).
Now for the actual problem, your references to the columns in ebaylinked in your trigger code are pretty much mostly wrong. To use the values in the record you just updated, you need to use the pseudorecord NEW, which is a single record containing the current row of the table as it will be after the update completes. References like ebaylinked.QuantitySold are ambiguous, as they do not specify which row of data is the correct one.
Also, you cannot refer to other rows in the triggering table. Your clauses SET ... ebaylinked.Processed=0 ... WHERE ... ebaylinked.Processed = 1 are thus both redundant and wrong, since the only row of ebaylinked your row trigger can see is the current one.
Your trigger code should thus be something like
CREATE TRIGGER `ebaylinked_update_product`
AFTER UPDATE ON `ebaylinked`
FOR EACH ROW
UPDATE product
SET product.product_stock = product.product_stock - NEW.QuantitySold
WHERE product.eBay_ID = NEW.ebay_ID;
Note I'm ignoring the processed column since it does nothing useful (provided the triggering insert is wrapped in a transaction), but if you absolutely must use it, you would change your trigger to before row as follows:
DELIMITER //
CREATE TRIGGER `ebaylinked_update_product`
BEFORE UPDATE ON `ebaylinked`
FOR EACH ROW
BEGIN
IF NEW.processed = 1 THEN
UPDATE product
SET product.product_stock = product.product_stock - NEW.QuantitySold
WHERE product.eBay_ID = NEW.ebay_ID;
SET NEW.processed = 0;
END IF;
END;
//
DELIMITER ;
Note the space between DELIMITER and whatever follows it. This directive is necessary in some clients when the trigger body contains multiple statements terminated by semicolons.
Hope that helps.
PS: You could do this with the trigger calling a stored procedure, but for something this simple I think it would add more complexity than it would be worth.
What is ebaylinked? You should be getting an error when you define the trigger.
If you want to update the table defined by the trigger, then you should use a BEFORE UPDATE trigger. So, I think you intend:
DELIMITER $$
CREATE TRIGGER `Update` BEFORE UPDATE ON `ebaylinked`
FOR EACH ROW
BEGIN
UPDATE product p
SET p.product_stock = p.product_stock - new.QuantitySold
WHERE p.eBay_ID = new.ebay_ID AND new.Processed = 1;
SET new.Processed = 0;
END; $$
DELIMTER ;
I have been trying to create a Trigger, however my attempts have been unsuccessful. I seem to be getting an error (#1064), which I have no solution for. Can somebody explain or demonstrate any faults in the syntax.
Let me specify:
I have delivery_id as primary key in delivery table,
I also have delivery_id as a foreign key in entry_log table.
By comparing both id's(if true), will return a text referring to the output of the bit (either 0 or 1)
DELIMITER //
DROP TRIGGER IF EXISTS entry_trigger//
CREATE TRIGGER entry_trigger BEFORE INSERT ON entry_log
FOR EACH ROW
BEGIN
DECLARE #xentry VARCHAR(45)
DECLARE #inta bit
SET #inta = SELECT allowed
FROM delivery
WHERE delivery.delivery_id = entry_log.delivery_id;
CASE
when #inta = 0 then #xentry = 'Acces Denied'
when #inta = 1 then #xentry = 'Acces Allowed'
END CASE
INSERT INTO entry_log(entry_time,access_allowed) VALUES(now(),#xentry);
END
//
This is assuming that you use MySQL. In the body of the trigger you use
WHERE delivery.delivery_id = entry_log.delivery_id;
I think you want to compare to the entry_log entry that the trigger is running on, right? In that case you must use this syntax:
WHERE delivery.delivery_id = NEW.delivery_id;
see here for more examples.
UPDATE
I see that also you try to do an INSERT INTO entry_log within the TRIGGER. This will of course not work, because you would create an infinite recursive loop. Within the
body of the trigger you can do unrelated table access, but not into the table you are inserting. You can change the values to be inserted by the trigger by setting NEW.xyz = whatever
UPDATE 2
I doubt, that your CASE statement is correct. At least it must end with END CASE. You can use IF here, since you don't have many cases to address. If you must use CASE this post might help you: MYSQL Trigger set datetime value using case statement
UPDATE 3
I am not sure, but I think you need brackets around the variable setting statement. try this trigger definition:
DELIMITER //
DROP TRIGGER IF EXISTS entry_trigger//
CREATE TRIGGER entry_trigger BEFORE INSERT ON entry_log
FOR EACH ROW
BEGIN
SET #inta = (SELECT allowed
FROM delivery
WHERE delivery.delivery_id = NEW.delivery_id);
SET NEW.access_allowed = #inta;
SET NEW.entry_time = NOW();
END
//
Note, that this is written out of my head, so beware of syntax errors in my script.
I have a simple DB-table with few fields for articles database among that is a TimeStamp containing the time of the last update made on the article.
I use "ON UPDATE CURRENT_TIMESTAMP"
Problem is that I want to update only if some fields of this record have changed, not all.
i.e. For each article, I have a field giving the number of time the article has been read by visitors. must not be updated after each web visit... only if I change the title, authors, etc...
Ideally with a nice mysql command...
I have coded the following:
CREATE TRIGGER `actu_lastupdate_date` BEFORE UPDATE ON `actuality`
FOR EACH ROW BEGIN
if NEW.title <> OLD.title OR NEW.chapeau = OLD.chapeau OR NEW.content = OLD.content
then
SET NEW.LastUpdate_date = current_timestamp;
end if;
END
it seems that even if another record field is changing, the Timestamp is updated. There should be something bad somewhere.
I'll look into it
You could write a trigger to add the timestamp on updates
delimiter |
CREATE TRIGGER actu_lastupdate_date AFTER UPDATE on actuality
FOR EACH ROW
BEGIN
if (NEW.title <> OLD.title
OR NEW.chapeau <> OLD.chapeau
OR NEW.content <> OLD.content)
AND (NEW.other_column = OLD.other_column
OR NEW.other_column2 = OLD.other_column2)
then
SET NEW.LastUpdate_date = current_timestamp;
end if;
END
|
delimiter ;
I don't know if this is possible, but I have a column named active in a table. Whenever the active column gets changed, I would like to reset the date in the date column, but ONLY if the active column gets changed.
If other columns are changed but not the active column, then the date would remain the same.
something like
DELIMITER //
CREATE TRIGGER updtrigger BEFORE UPDATE ON mytable
FOR EACH ROW
BEGIN
IF NEW.active <> OLD.active THEN
SET NEW.date = '';
END IF;
END
//
Ran into an issue with the IF test in the #2 example. When one of the values is null the <> test returns null. This leads to the test not getting met and the action of the trigger will not get run even though the one value does not equal null at all. To fix this I came up with this test that uses <=> (NULL-safe equal). Hope this helps someone out.
DELIMITER $$
DROP TRIGGER IF EXISTS updtrigger ;
$$
CREATE TRIGGER updtrigger AFTER UPDATE
ON yourTable FOR EACH ROW
BEGIN
IF ((NEW.active <=> OLD.active) = 0) THEN
SET NEW.date = '';
END IF;
$$