Firstly let me say I'm new to and just getting my head around MySQL and finding date manipulation has its challenges. It seems to me it should be possible to have three columns:
column A contains date member joined 2020-01-12 for example, mapped from a form.
column B contains the length of membership in years 1 or 5, currently entered manually
Then calculate expiry 'date A'+ 'integer B' Year inserted in column C on member creation or update
It's OK to do manually but I feel it should be something automatic.
If anyone can give me a start or point to a tutorial that might help I'd be grateful.
In MySql you can use DATE_ADD() funciton:
SELECT columnA, columnB, DATE_ADD(columnA, INTERVAL columnB YEAR) AS EXPIRY;
Use this web page as reference.
You could define triggers BEFORE INSERT and/or BEFORE UPDATE which will do the job for you:
BEFORE INSERT trigger:
DROP TRIGGER IF EXISTS before_insert;
DELIMITER $$
CREATE TRIGGER before_insert
BEFORE INSERT ON `my_table`
FOR EACH ROW
BEGIN
SET NEW.`valid` = DATE_ADD(NEW.`date`, INTERVAL NEW.`membership` YEAR);
END$$
DELIMITER ;
BEFORE UPDATE trigger:
DROP TRIGGER IF EXISTS before_update;
DELIMITER $$
CREATE TRIGGER before_update
BEFORE UPDATE ON `my_table`
FOR EACH ROW
BEGIN
SET NEW.`valid` = DATE_ADD(NEW.`date`, INTERVAL NEW.`membership` YEAR);
END$$
DELIMITER ;
It is quite enough to insert both date and membership values during insert (obviously) or to update membership value on already inserted record(s).
Your Column C is the valid column in both queries.
Related
I'm trying to insert a row into a table after updating a row in this same table. I was trying to do this using a trigger. But I found that it's not possible to do that in this method.
What i'm trying to achieve is, I have this
tbl_eq_maintenance(eq_no,eq_name,last_rep_date,next_rep_date,status)
Values(EQ-30,treadmill,08-10-2018,18-10-2018,0).
I want to update this row's status into "1" and after that insert a new row into the same table as follows.
(EQ-30,treadmill,18-10-2018,28-10-2018,0).
How can i do this with a trigger or if can't is there a workaround for this.
The trigger I wrote as below.
DELIMITER $$
CREATE TRIGGER add_maintenance
AFTER UPDATE on tbl_eq_maintenance
FOR EACH ROW
BEGIN
DECLARE next_rep_date DATE;
DECLARE new_m_cycle INT(5);
SELECT m_cycle INTO new_m_cycle FROM tbl_equipments WHERE eq_no = NEW.eq_no;
SET next_rep_date = DATE_ADD(CURDATE(), INTERVAL new_m_cycle DAY);
INSERT INTO tbl_eq_maintenance (eq_no,eq_name,last_rep_date,next_rep_date)
Values (NEW.eq_no,NEW.eq_name,CURDATE(),next_rep_date);
END$$
DELIMITER ;
When you update the table, this trigger will execute and insert an new record in the table.
Refer to this link
I have two tables:
oee_main
oee_client
I already have an after insert trigger on oee_main as follows:
CREATE TRIGGER `oee_upd` AFTER INSERT ON `oee_main`
FOR EACH ROW UPDATE oee_client
SET END_DATE= NOW() where END_DATE IS NULL
I now need to develop the trigger even more so that the newly inserted row in oee_main will not only update the END_DATE of oee_client to NOW() where END_DATE is NULL but to only update the row(s) of oee_client where the column called Machine_ID is equal to the newly inserted column named NAME in oee_main.
I have tried adding this to the where condition of the above trigger to no success:
where END_DATE IS NULL and Machine_ID = new.`oee_main`.`NAME`
Therefore what I am after is that when a new record is inserted in oee_main which has a value of for example '2' in column 'NAME' the trigger updates only the columns END_DATE of oee_client where NULL and where Machine_ID of oee_client is equal to the newly inserted value of NAME in oee_main.
Thanks
I think this is the logic you want:
DELIMITER $$
CREATE TRIGGER `oee_upd` AFTER INSERT ON `oee_main`
FOR EACH ROW
BEGIN
UPDATE oee_client c
SET c.END_DATE = NOW()
WHERE c.END_DATE IS NULL AND c.Machine_ID = new.NAME;
END$$
DELIMITER ;
Remember to use the delimiter statement whenever you define triggers, stored procedures and functions. It will help prevent errors in the future.
As for your error, you don't need to mention the table name when you use NEW.
As an outsider, I find it confusing that NAME in one table matches MACHINE_ID in another table. I would expect both tables to have a column called MACHINE_ID.
I have a table reservation details which has columns and one of the column is creation date.
I want to create a trigger which checks whether the creation date is first day of the year. If it is then, insert values into to master_ids table. I have created a trigger but don't know whether its correct or not. My project is in php.
CREATE TRIGGER upd_check BEFORE INSERT ON ColdStorage.ReservationDetails
FOR EACH ROW
BEGIN
IF NEW.creationdate = DATE_FORMAT(NOW() ,'%Y-01-01') then
UPDATE master_ids SET nextOccId="1",nextResId="1",nextAgrnoId="1",nextRecNo="1";
END if;
END;
Please suggest me some solutions. I also want that if the date is 01-01-yy then.. its should not insert the row which i m inserting.
You need to change the delimiter. MySQL sees the first ; as the end of the CREATE TRIGGER statement, and thinks the whole statement ends there. So you have to change the delimiter like this:
/* Change the delimiter */
DELIMITER $$
CREATE TRIGGER upd_check BEFORE INSERT ON ColdStorage.ReservationDetails
FOR EACH ROW
BEGIN
IF NEW.creationdate = DATE_FORMAT(NOW() ,'%Y-01-01') then
insert into master_ids values ('0','0','0','0');
END if;
END$$
/* the CREATE TRIGGER statement ends with new delimiter */
/* change the delimiter back to ; */
DELIMITER ;
I haven't tested it, but it seems fine. What bothers me is that this will work just for one day during the year, the other 364 (365) days it is completely useless, and looks like an overhead.
i have a table as below
Table name: sda_user_eform_data
ack_no Name Description
1 name1 This is name1
2 name2 This is name2
3 name3 This is name3
i have another table sda_user_eform_data_bckup which has exactly the same structure as sda_user_eform_data. I want to store only 5 rows(latest rows) in the sda_user_eform_data and whenever the ackno is greater than 5 the old values should be moved to the second(sda_user_eform_data_bckup) table.
For this first i have copied all the rows from sda_user_eform_data table to the sda_user_eform_data_bckup table. then i have created the following trigger where the i have checked the ack_no and if its greater than 5 then its deleted the oldest ack_no and insert the new value to the bckup table.
DELIMITER $$
create
trigger 'copy_eform_data' AFTER INSERT
on asdb.sda_user_eform_data
for each row begin
if (select count(s.ack_no) from asdb.sda_user_eform_data s)>5 then
delete from asdb.sda_user_eform_data where old.ack_no=(select min(s.ack_no) from asdb.sda_user_eform_data s);
insert into asdb.sda_user_eform_data_bckup select * from asdb.sda_user_eform_data where ack_no=select max(s.ack_no) from asdb.sda_user_eform_data s;
end$$
DELIMITER ;
I am not able to find out where the trigger went wrong as its not executing. Any suggestion is highly welcoming.
Thanks in advance.
That's most likely because your trigger doesn't even exist. The problem is here
create
trigger 'copy_eform_data'
With the single quotes copy_eform_data is a string.
Have a look at this post: When to use single quotes, double quotes, and backticks?
Also you should read up about the NEW and OLD keywords in triggers. Your trigger probably never matches a line.
And here
where ack_no=select max(s.ack_no) from asdb.sda_user_eform_data s
you're missing parantheses.
Apart from all that, I didn't really have a deep thought about your logic to be honest, because I don't see a point in your whole question. Why would you want to have duplicate data? I guess out of performance reasons? Have your table indexed appropriately and there should be no problem. And to get the 5 latest entries of your table simply use
FROM yourTable
ORDER BY when_was_the_entry_created_or_something DESC
LIMIT 5
You can have columns like
created timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
to use in your ORDER BY. And you probably want an index on that column.
I doing some changes in your query. Revert back if it helps.
DELIMITER $$
create
trigger 'copy_eform_data' AFTER INSERT
on asdb.sda_user_eform_data
for each row begin
insert into asdb.sda_user_eform_data_bckup
select * from asdb.sda_user_eform_data ORDER BY ack_no DESC LIMIT 1
if (select count(s.ack_no) from asdb.sda_user_eform_data s)>=5 then
delete from asdb.sda_user_eform_data;
end$$
DELIMITER ;
But make sure that when you are entering records into "asdb.sda_user_eform_data" after clearing table, "ack_no" should again start from 1
I was searching for a solution to create trigger for deleting records and came across your forum. However, I know this is over a year post and you've most likely solved the issue, but I would like to try to answer your post. I think you need a "End If" before your end $$.
So it would be:
DELIMITER $$
create
trigger 'copy_eform_data' AFTER INSERT
on asdb.sda_user_eform_data
for each row begin
if (select count(s.ack_no) from asdb.sda_user_eform_data s)>5 then
delete from asdb.sda_user_eform_data where old.ack_no=(select min(s.ack_no) from asdb.sda_user_eform_data s);
insert into asdb.sda_user_eform_data_bckup select * from asdb.sda_user_eform_data where ack_no=select max(s.ack_no) from asdb.sda_user_eform_data s;
END IF;
end$$
DELIMITER ;
I have a small question. I have 2 tables:
CREATE TABLE park(parkcode CHAR(5), name CHAR(15));
CREATE TABLE ticket(date_purchase_ticket TIMESTAMP, parkcode CHAR(5));
What I am trying to do is to create a trigger that when I want to delete a row from table park, the trigger first looks to see if there were any purchases after a certain date. And only if there were no purchases after a certain date then you can delete that row from the table park.
You need to think about making a procedure that you can call when you want to delete a row from park.
Something along the lines of:
DELIMITER //
CREATE PROCEDURE DeleteIfNoPurchases (IN code CHAR(5),
IN date TIMESTAMP)
BEGIN
IF (SELECT MAX(date_purchase_ticket)
FROM ticket
WHERE parkcode = code) < date THEN
DELETE FROM park WHERE parkcode = code;
END IF;
END//
DELIMITER ;
Then you can call it with the code you want to delete and the timestamp you want to test against.
You can not prevent deleting a row with trigger.