How to add a trigger if column has updated with specific string - mysql

I want to add a trigger if name has update with "NEW_" string. Below is my current trigger but its working without checking the updated value contain "NEW_" . please advice
if user updates name from "Ann" to "NEW_Ann" trigger should work.
if user updates name from "Ann" to "Ann111" trigger shouldn't work
Code:
$this->execute("ALTER TABLE `users`
ADD COLUMN `date_` TIMESTAMP NULL DEFAULT NULL");
$this->execute("CREATE TRIGGER `update_user_deleted_date` BEFORE UPDATE ON `users` FOR EACH ROW BEGIN
IF (NEW.name!= OLD.name) THEN
SET NEW.date_deleted = NOW();
END IF;
END ;");

Use this:
CREATE TRIGGER update_user_deleted_date BEFORE UPDATE ON users
FOR EACH ROW BEGIN
IF (LOCATE('NEW_', NEW.name) != 0) THEN
SET NEW.date_deleted = NOW();
END IF;
END;
LOCATE('NEW_', NEW.name) != 0 means that the location of string "NEW_" is found

Related

How to check NEW value exists in BEFORE UPDATE Trigger Mysql

I have table Demo:
create table Demo (
id int(10) auto_increment primary key,
text varchar(30) default null,
istrue boolean default false
);
I want create a update trigger such that:
When Update Demo set istrue = false where id = 1; (not "set text = ") -> normal update.
When Update Demo set text= 'abc' where id = 1; ("set text = ") -> SET NEW.text := concat(OLD.text,'#', NEW.text);
I have implemented trigger as follows:
DELIMITER $$
CREATE TRIGGER update_text
BEFORE update ON Demo
FOR EACH ROW
BEGIN
IF (exists(SELECT NEW.text)) THEN -- how to check NEW.text exists???
SET NEW.text := concat(OLD.text,'#', NEW.text);
END IF;
END$$
DELIMITER ;
But it isn't working! Please help. Thank You!!! (My English is not good. Hope everyone sympathized)
CREATE TRIGGER update_text
BEFORE update
ON Demo
FOR EACH ROW
SET NEW.text = CASE WHEN OLD.text <=> NEW.text
THEN NEW.text
ELSE CONCAT(OLD.text, '#', NEW.text)
END;
PS. Single-statement trigger - BEGIN-END and DELIMITER reassing not needed.
After the deep investigation I have found the way to detect that the field value was set in UPDATE statement.
However, I can't guarantee its reliability. I only check does the substring '`text`' is present in current query text - but there is a lot of situations when this check will give errorneous result, for example, wrong TRUE if this substring is a part of new value, or wrong FALSE if the fieldname is not wrapped with backticks. So be aware.
CREATE TRIGGER update_text
BEFORE update
ON demo
FOR EACH ROW
SET NEW.`text` = CASE WHEN LOCATE('`text`', ( SELECT info
FROM information_schema.processlist
WHERE id = CONNECTION_ID()
)
)
THEN CONCAT(OLD.`text`, '#', NEW.`text`)
ELSE NEW.`text`
END;
fiddle

Question about Update on Trigger with condition

I can't find the correct syntax for the trigger I tried to code.
I want to update a timestamp every time there is an update on the table but only for specific rows. I want to update the "UPDATE_TIME" only for the last "N_TACHE"
I can't find how to use SET with a where clause.
CREATE TRIGGER "time_on_update"
BEFORE UPDATE ON "SAVE_UPDATE"
FOR EACH ROW
BEGIN
IF
(NEW.DATE_DE_RDV <> OLD.DATE_DE_RDV)
OR
(NEW.ADRESSE <> OLD.ADRESSE)
OR
(NEW.CODE_POSTAL <> OLD.CODE_POSTAL)
OR
(NEW.VILLE <> OLD.VILLE)
THEN
SET (NEW.UPDATE_TIME = current_timestamp WHERE N_TACHE= (SELECT MAX(N_TACHE));
END IF;
If you have any suggestion I take it.
Thanks in advance
EDIT :
This one is working but it update all the rows and I just want to update "update_time" for the last value of "N_TACHE" when "RDV","ADRESSE","CODE_POSTAL" or "VILLE" is updated
DELIMITER $$
CREATE TRIGGER `time_on_update`
BEFORE UPDATE ON `SAVE_UPDATE`
FOR EACH ROW
BEGIN
IF
(SELECT MAX(N_TACHE)
FROM SAVE_UPDATE
WHERE
((NEW.DATE_DE_RDV <> OLD.DATE_DE_RDV)
OR
(NEW.ADRESSE <> OLD.ADRESSE)
OR
(NEW.CODE_POSTAL <> OLD.CODE_POSTAL)
OR
(NEW.VILLE <> OLD.VILLE)))
THEN
SET NEW.UPDATE_TIME = current_timestamp;
END IF;
END
$$
DELIMITER ;

How to use Case-When and Update in Trigger?(Error in my code)

I tried to create below Trigger but I have an Error.
Can I Use Update or use 'case when' in trigger?
Please help me to fix my issue here.
Code Explanation:
I want to update my existing row after insert or update.
Do not change the 'FUSDate1' or 'FUSDate2' If I didn't add anything to the 'FUSDate1' or 'FUSDate2'
Update the FUSDate to the New One or Inserted one If I Updated or inserted data to FUSDate
Code:
delimiter //
create trigger SafetyCertificationTRG
after insert on SafetyCertification
for each row
begin
case when (FUSDate1='' or FUZDate1 is NULL) then (FUZDate1=OLD.FUSDate1) else (update SafetyCertification set FUZDate1=NEW.FUSDate1) end;
case when (FUSDate2='' or FUZDate2 is NULL) then (FUZDate2=NEW.FUSDate2) else (update SafetyCertification set FUZDate2=NEW.FUSDate2) end;
end //
delimiter ;
Edit: I am going to add some information here to make the question more clear.
I have one column as FUS that can be get these 3 values only:('FUS1', 'FUS2' and 'FUS3')
I have 3 other columns: FUSDate1, FUSDate2, FUSDate3.
I want to save the Current Date to The FUSDate1 Or FUSDate2 Or FUSDate3 based on the user User Selection of FUS. (They are in same Table)
I used the provided answer and change it to this but I cannot do the above.
Code: This code is just for FUS1 and FUSDate1
delimiter //
CREATE TRIGGER SafetyCertification_bu
BEFORE UPDATE ON SafetyCertification
FOR EACH ROW
BEGIN
-- detect a change made to a value in col
IF OLD.FUS <=> NEW.FUS THEN
-- value of col is not changed, so do nothing
DO 0;
ELSE
-- we detected a new value was assigned to col
IF OLD.FUS ='%FUS1%' THEN
-- we can override the new value, keep it the same
SET NEW.FUSDate1 = CURDATE();
END IF;
END IF;
END //
delimiter ;
Another code that I expected to do my work but still have problem, Does not update Like above Code:
delimiter //
CREATE TRIGGER SafetyCertification_bu
BEFORE INSERT ON SafetyCertification
FOR EACH ROW
BEGIN
IF NEW.FUS='%FUS1%' THEN
SET new.FUSDate1=MD5(CURDATE());
END IF;
END //
delimiter ;
Update 3:
The Third code that provided in answer does not add anything to the FUSdate1 and 2 and 3 when i update or insert any data.
Code
DELIMITER $$
CREATE TRIGGER SafetyCertification_bu
BEFORE UPDATE ON SafetyCertification
FOR EACH ROW
BEGIN
-- set one of the `fusdateN` columns to current date
-- which column to set depends on the value assigned to `fus`
IF NEW.fus = 'FUS1' THEN
SET NEW.fusdate1 = DATE(NOW());
ELSEIF NEW.fus = 'FUS2' THEN
SET NEW.fusdate2 = DATE(NOW());
ELSEIF NEW.fus = 'FUS3' THEN
SET NEW.fusdate3 = DATE(NOW());
END IF;
END$$
DELIMITER ;
A couple of notes:
A trigger cannot issue an UPDATE against the table that fired the trigger, this is prohibited.
The unqualified references (e.g. FUSDate1 and FUZDate1) are not valid. Those references don't resolve to anything.
The reference to OLD.FUSDate1 is invalid in the context of an AFTER INSERT trigger. In an UPDATE trigger, the OLD.col refers to the value of col before the update.
The expression (FUZDate1=OLD.FUSDate1) is not an assignment, it's a comparison that's going to return 0, 1 or NULL.
If we want to trigger on an UPDATE and an INSERT, that will require two separate triggers.
If we want to modify the contents of the current row, we can use BEFORE trigger instead of AFTER.
I want to update my existing row after insert or update.
It would be much easier to apply changes before the row is inserted or updated. We can assign a value to a column col by referencing NEW.col in an assignment in a BEFORE INSERT or BEFORE UPDATE trigger. For example:
SET NEW.col = expr;
Do not change the FUSDate1 or FUSDate2 If I didn't add anything to the FUSDate1 or FUSDate2
This seems pretty straightforward. Just don't make any assignments to NEW.FUSDate1 or NEW.FUSDate2.
Update the FUSDate to the New One or Inserted one If I Updated or inserted data to FUSDate
The example proposed trigger contains references to FUZDate1 or FUZDate2, but there's no mention of these columns in the specification. The specification is confusing.
An UPDATE statement will assign a value to a column, no need for a trigger to do that. An INSERT statement can assign a value to a column, again, no need for a trigger for that.
The specification is not clear. Providing example starting state (rows in the table), and example INSERT or UPDATE statements, and the desired state after the statement is executed would go a long ways towards clarifying the requirements.
A demonstration of a BEFORE UPDATE trigger that prevents a new value being assigned to a particular column:
DELIMITER $$
CREATE TRIGGER SafetyCertification_bu
BEFORE UPDATE ON SafetyCertification
FOR EACH ROW
BEGIN
-- detect a change made to a value in col
IF OLD.col <=> NEW.col THEN
-- value of col is not changed, so do nothing
DO 0;
ELSE
-- we detected a new value was assigned to col
IF OLD.col IS NOT NULL THEN
-- we can override the new value, keep it the same
SET NEW.col = OLD.col;
END IF;
END IF;
END$$
DELIMITER ;
For what this example trigger achieves, we don't necessarily need that many IF conditions; those are included as a demonstrate some of the checks we can perform, how we can make references to the existing value of col and the new value assigned to col.
FOLLOWUP
Based on the update information in the question, here's an example of a BEFORE UPDATE trigger that satisfies the specification.
This is for the UPDATE action. To get this same behavior with an INSERT statement, this trigger definition needs to be repeated, with BEFORE INSERT in place of BEFORE UPDATE.
(I would use the name _bu for the before update trigger, and _bi for before insert trigger.)
DELIMITER $$
CREATE TRIGGER SafetyCertification_bu
BEFORE UPDATE ON SafetyCertification
FOR EACH ROW
BEGIN
-- set one of the `fusdateN` columns to current date
-- which column to set depends on the value assigned to `fus`
IF NEW.fus = 'FUS1' THEN
SET NEW.fusdate1 = DATE(NOW());
ELSEIF NEW.fus = 'FUS2' THEN
SET NEW.fusdate2 = DATE(NOW());
ELSEIF NEW.fus = 'FUS3' THEN
SET NEW.fusdate3 = DATE(NOW());
END IF;
END$$
DELIMITER ;
second followup
To answer the question about using CASE WHEN statement in the context of a MySQL stored program...
We could implement the example trigger (directly above in this answer) replacing the IF-THEM with either of the two forms of the CASE statement.
either
CASE
WHEN NEW.fus = 'FUS1' THEN
SET NEW.fusdate1 = DATE(NOW());
WHEN NEW.fus = 'FUS2' THEN
SET NEW.fusdate2 = DATE(NOW());
WHEN NEW.fus = 'FUS3' THEN
SET NEW.fusdate3 = DATE(NOW());
END CASE;
-or-
CASE NEW.fus
WHEN 'FUS1' THEN
SET NEW.fusdate1 = DATE(NOW());
WHEN 'FUS2' THEN
SET NEW.fusdate2 = DATE(NOW());
WHEN 'FUS3' THEN
SET NEW.fusdate3 = DATE(NOW());
END CASE;
note
The CASE statement is available in MySQL stored programs; outside of a stored program, it is not a valid SQL statement.
Also, we should not confuse this CASE statement with the CASE expression. The CASE expression is valid in the context of a SQL statement, such as a SELECT or UPDATE statement.
DEMONSTRATION
"I examined the Trigger, But unfortunately does not save anything in fusDates."
#Christiano: here is a simple demonstration
create table
CREATE TABLE `safety_certification`
( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
, fus VARCHAR(5)
, fusdate1 DATE
, fusdate2 DATE
, fusdate3 DATE
) ENGINE=INNODB
;
populate table with demonstration rows
INSERT INTO `safety_certification` (id, fus, fusdate1, fusdate2, fusdate3) VALUES
( 1, '', NULL, NULL, NULL)
,( 2, '', NULL, NULL, NULL)
,( 3, '', NULL, NULL, NULL)
,( 4, '', NULL, NULL, NULL)
,( 5, '', NULL, NULL, NULL)
;
create trigger
DELIMITER $$
CREATE TRIGGER `safety_certification_bu`
BEFORE UPDATE ON `safety_certification`
FOR EACH ROW
BEGIN
-- set one of the `fusdateN` columns to current date
-- which column to set depends on the value assigned to `fus`
IF NEW.fus = 'FUS1' THEN
SET NEW.fusdate1 = DATE(NOW());
ELSEIF NEW.fus = 'FUS2' THEN
SET NEW.fusdate2 = DATE(NOW());
ELSEIF NEW.fus = 'FUS3' THEN
SET NEW.fusdate3 = DATE(NOW());
END IF;
END$$
DELIMITER ;
updates will exercise BEFORE UPDATE trigger we just defined
UPDATE `safety_certification` sc SET sc.fus = 'FUS1' WHERE sc.id = 1 ;
UPDATE `safety_certification` sc SET sc.fus = 'FUS2' WHERE sc.id = 2 ;
UPDATE `safety_certification` sc SET sc.fus = 'FUS3' WHERE sc.id = 3 ;
UPDATE `safety_certification` sc SET sc.fus = 'FUS4' WHERE sc.id = 4 ;
display contents of table
SELECT * FROM `safety_certification`;
returns:
id fus fusdate1 fusdate2 fusdate3
------ ------ ---------- ---------- ------------
1 FUS1 2018-05-04 (NULL) (NULL)
2 FUS2 (NULL) 2018-05-04 (NULL)
3 FUS3 (NULL) (NULL) 2018-05-04
4 FUS4 (NULL) (NULL) (NULL)
5 (NULL) (NULL) (NULL)
seems like the trigger is populating the columns fusdate1, fusdate2 and fusdate3 per the specification, when some particular values are assigned to fus
I had a same problem and I used two trigger,
First trigger send data to the other table, so now you can create another trigger to send this data to the first table. I think it is low performance but it is the only way that I reached to it. I hope others have another solution for u.

MySQL: Trigger Before Update Not Working

I'm trying to get a trigger to run before an update is processed on a per record level of a table.
What I'm trying to do is when an update occurs on a record for the qst_title column, if the column qst_perma_title is NULL then the qst_perma_title column is updated with the value in the qst_title column and the qst_title column is updated as per the original update query.
I'm using the code below but no errors are shown and the column qst_perma_title isn't updated.
The current values are:
qst_title = 'Old Title'
qst_perma_title = NULL
query
UPDATE TD_QUESTION SET qst_title = 'New Title Value' WHERE qst_id = 1;
trigger
DELIMITER //
CREATE TRIGGER TRG_QST_UPD
BEFORE UPDATE ON TD_QUESTION
FOR EACH ROW
BEGIN
IF OLD.`qst_perma_title` IS NULL THEN
SET NEW.`qst_perma_title` = OLD.`qst_title`;
END IF;
END//
DELIMITER ;
CREATE TRIGGER TRG_QST_UPD
BEFORE UPDATE ON TD_QUESTION
FOR EACH ROW
IF OLD.qst_perma_title IS NULL THEN
SET NEW.qst_perma_title = OLD.qst_title;
END IF;
First run this query and then try updating. I checked, it is working fine for me.

Mysql current date trigger

I have the following trigger
CREATE TRIGGER `qc_date_trigger` AFTER UPDATE ON `brand`
FOR EACH ROW BEGIN
IF NEW.brandQC = '1' THEN
SET #brandQCDate = CURDATE();
ELSE
SET #brandQCDate = NULL;
END IF;
END
For some reason it does not update my Date field into the current date when QC is = 1. I've checked the mysql doc and it should work. Any ideeas?
If your column is named brandQCDate, then remove the #. The # makes it a user defined variable, not the column. Also you want to make this a BEFORE UPDATE trigger.
CREATE TRIGGER `qc_date_trigger` BEFORE UPDATE ON `brand`
FOR EACH ROW BEGIN
IF NEW.brandQC = '1' THEN
SET NEW.brandQCDate = CURDATE();
ELSE
SET NEW.brandQCDate = NULL;
END IF;
END