how to declare variable phpmyadmin mysql triggers properly? - mysql

I have a database where whenever residential address update in user table I want it to store in history table of user. For that I'm trying to write triggers but failing miserably in phpmyadmin. Also it's not giving me proper reason why so I can correct it. This is what I have done so far.
DROP TRIGGER IF EXISTS `record_history`;
CREATE TRIGGER `record_history` AFTER UPDATE ON `s_user`
FOR EACH ROW
BEGIN
DECLARE date_current datetime;
DECLARE residential_address varchar(1000);
SET #date_current = NOW();
SET #residential_address = NEW.residential_address;
IF (#residential_address <> OLD.residential_address AND #residential_address != "" AND #residential_address IS NOT NULL) THEN
INSERT INTO history_residential_address (`s_u_id`, `residential_address`, `status`, `date_added`, `date_updated`) VALUES
(OLD.s_u_id, #residential_address, 1, #date_current, #date_current);
END IF;
END;
delimiter ;

A cleaner version of your code
DROP TRIGGER IF EXISTS `record_history`;
delimiter $$
CREATE TRIGGER `record_history` AFTER UPDATE ON `s_user`
FOR EACH ROW
BEGIN
IF (new.residential_address <> OLD.residential_address AND new.residential_address <> "" AND new.residential_address IS NOT NULL) THEN
INSERT INTO history_residential_address (`s_u_id`, `residential_address`, `status`, `date_added`, `date_updated`) VALUES
(OLD.s_u_id, new.residential_address, 1, now(), now());
END IF;
END $$
delimiter ;
If you are still having problems please add sample data from s_user as text to the question.

Related

Generic logging with differences using triggers

I am trying to write a trigger that would simplify logging changes when a record is updated. I have a stored procedure that does an INSERT to a logging table called log_update and a trigger that does the job for 1 field:
DROP TRIGGER IF EXISTS `parents_update`;
DELIMITER $$
CREATE TRIGGER `parents_update` AFTER UPDATE ON `parents`
FOR EACH ROW
BEGIN
IF ( NEW.motherLastName != OLD.motherLastName ) THEN
CALL log_update( 'parent', NEW.id, 4, CONCAT( OLD.motherLastName, ' > ', NEW.motherLastName ) );
END IF;
END;
$$
DELIMITER ;
Is it a way to make this more generic like provide list of fields:
( 'motherFirstName', 'motherLastName', 'fatherFistName', .... )
and loop through this list with a parameter for the single IF statement?
Edit:
I come up with such loop:
DROP TRIGGER IF EXISTS `parents_update`;
DELIMITER $$
CREATE TRIGGER `parents_update` AFTER UPDATE ON `parents`
FOR EACH ROW
BEGIN
DECLARE _fieldName VARCHAR(25);
DECLARE done INT DEFAULT FALSE;
DECLARE fieldsCursor CURSOR FOR SELECT fieldName FROM log_fields WHERE tableName = 'parents';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN fieldsCursor;
the_loop : LOOP
FETCH fieldsCursor INTO _fieldName;
IF done THEN
LEAVE the_loop;
END IF;
-- _fieldName will contain values such 'motherLastName'
IF ( NEW ( _fieldName ) != OLD ( _fieldName ) ) THEN
CALL log_update( 'parent', NEW.id, 4, CONCAT( OLD ( _fieldName ), ' > ', NEW ( _fieldName ) ) );
END IF;
END LOOP the_loop;
CLOSE fieldCursor;
END;
$$
DELIMITER ;
where table log_fields will contain fields to check. Now I am facing the problem of how to access the NEW. or OLD. property if the field name is in a variable.
I would say you can use prepared statements to achieve it, but unfortunately it is not supported in triggers.
You can read more about it here: http://dev.mysql.com/doc/refman/5.1/en/stored-program-restrictions.html OR answer here: Alternative to using Prepared Statement in Trigger with MySQL
which mean you can't create dynamic SQL query in your trigger the same applied to NEW. or OLD. variables dinamic build, so the only way is create separate triggers for each table with listed all column names one by one

Update one mysql column when another is edited

I'm trying to make a datetime field that automatically gets updated with the current time only if there was a change to a certain field.
It seems I have a syntax error.
CREATE OR ALTER TRIGGER last_progress_date
ON wp_task_mgr
AFTER UPDATE
AS BEGIN
IF UPDATE (progress_percentage)
SET last_progress_date = GETDATE()
END
Just for future reference, I found the answer here:
https://dba.stackexchange.com/questions/125203/simple-trigger-to-update-two-columns-in-one-table
MySQL query:
DELIMITER //
CREATE TRIGGER trig_1 before insert
ON <table_name> FOR EACH ROW
BEGIN
IF new.due_date is not null and new.end_date='' then
set new.end_date=new.due_date;
end if;
IF new.end_date is not null and new.due_date='' then
set new.due_date=new.end_date;
end if;
END;
//
DELIMITER //
CREATE TRIGGER trig_2 before update
ON <table_name> FOR EACH ROW
BEGIN
IF new.due_date <>old.due_date then
set new.end_date=new.due_date;
end if;
IF new.end_date <> old.end_date then
set new.due_date=new.end_date;
end if;
END;
//

I have error "#1363 - There is no NEW row in on DELETE trigger "

I have table "book" and "store_order" have relation
I want to make trigger(but it contain error):
DELIMITER $$
CREATE TRIGGER t1
before delete ON store_order
FOR EACH ROW
BEGIN
update book set number = number + NEW.quantity where ISBN = NEW.ISBN;
END
$$
DELIMITER ;
DELIMITER $$
CREATE
TRIGGER t2 AFTER delete
ON library.store_order
FOR EACH ROW BEGIN
update library.book
set library.book.number = (library.book.number + OLD.quantity)
where library.book.ISBN = OLD.ISBN;
END$$
DELIMITER ;
Use OLD instead of NEW when you want to get the deleted object.
for an example of my case. I'm getting the id of the newly added role by calling
NEW.id
and getting the same field's value while deleting by calling
OLD.id
Example:
DELIMITER $$
CREATE TRIGGER after_insert_role
AFTER INSERT ON role FOR EACH ROW
BEGIN
INSERT INTO `sync_mapping`
(`operation_type`, `table_name`, `oid`, `end_point`)
VALUES
('insert', 'role', NEW.id, 'new/role');
END $$
DELIMITER $$
CREATE TRIGGER after_delete_role
AFTER DELETE ON role FOR EACH ROW
BEGIN
INSERT INTO `sync_mapping` (`operation_type`, `table_name`, `oid`, `end_point`) VALUES
('delete', 'role', OLD.id, 'delete/role');
END $$
Whenever we are deleting the data
USE
OLD. instead of NEW.
CREATE TRIGGER user_history_delete AFTER DELETE ON user FOR EACH ROW
INSERT INTO user_history(action , name )
VALUES ("Delete" , OLD.name );

Resultset from trigger MySQL

This is my first time using trigger and I'm having a bit of trouble.
I'm creating a notification system that when a new notification is created it will add a row to the notify table. What is added depends on what notification type it is.
So far I've tried:
DELIMITER $$
DROP TRIGGER IF EXISTS generate_notify $$
CREATE TRIGGER generate_notify
AFTER INSERT
ON notifications
FOR EACH ROW
BEGIN
SELECT #group := notify_group FROM notification_types WHERE type=NEW.type;
IF (#group <> 1) THEN
INSERT INTO notify (user_id, notification_id) VALUES (NEW.user_reference, NEW.id);
ELSE
INSERT INTO notify (user_id, notification_id) VALUES(
SELECT ID, NEW.id FROM user_customer WHERE clientID=NEW.user_reference
);
END IF;
END; $$
DELIMITER ;
I searched around and then changed it to:
DELIMITER $$
DROP TRIGGER IF EXISTS generate_notify $$
CREATE TRIGGER generate_notify
AFTER INSERT
ON notifications
FOR EACH ROW
BEGIN
DECLARE insert_user_id INT(11);
SELECT #group := notify_group FROM notification_types WHERE type=NEW.type;
IF (#group <> 1) THEN
INSERT INTO notify (user_id, notification_id) VALUES (NEW.user_reference, NEW.id);
ELSE
SELECT ID INTO insert_user_id FROM user_customer WHERE clientID=NEW.user_reference;
INSERT INTO notify (user_id, notification_id) VALUES(insert_user_id, NEW.id);
END IF;
END; $$
DELIMITER ;
I've also tried mixing the above 2 up and all I'm getting is either can not return result set or there is a syntax error with my select query.
(Also, I'm assuming that the NEW keyword is predefined for triggers?)
Your first try was actually on the right track, but you did not write the result of your SELECT into a variable. Returning a result set from a trigger is not possible.
DELIMITER $$
DROP TRIGGER IF EXISTS generate_notify $$
CREATE TRIGGER generate_notify
AFTER INSERT
ON notifications
FOR EACH ROW
BEGIN
DECLARE v_group INT;
SELECT notify_group INTO v_group FROM notification_types WHERE type=NEW.type;
IF (v_group <> 1) THEN
INSERT INTO notify (user_id, notification_id) VALUES (NEW.user_reference, NEW.id);
ELSE
INSERT INTO notify (user_id, notification_id) VALUES(
SELECT ID, NEW.id FROM user_customer WHERE clientID=NEW.user_reference
);
END IF;
END $$
DELIMITER ;

Trigger syntax error

My first time using triggers. Can anyone please explain why this trigger won't work? The error I'm getting is inconclusive (error near '' at line 5)
create trigger queue after update on downloads
for each row
begin
if NEW.completed = 1 then
insert into s_queue ( website_id ) values ( NEW.website_id );
end if;
end;
You need to change the delimiter from ; to something else, before defining any stored procedure/functions or triggers.
delimiter ||
create trigger queue after update on downloads
for each row
begin
if NEW.completed = 1 then
insert into s_queue ( website_id ) values ( NEW.website_id );
end if;
end||
delimiter;