I have an existing table with values already filled in. Last column is of type date.
My requirement is that if any value is updated, that row's corresponding date column should be automatically updated to the current date.
For example, if the table is as follows:
and if I change any of the values of col1 (78) /col2 (nvvb) /col3 (566) of say row no. 2 on date 18Nov2018, then the col4 of row 2 should automatically update to today's date of 18Nov2018 from existing 13-Oct-17.
I've checked existing topics by could not find an answer.
The closest I can find is this code, but it is not working for the above requirement:
create table if not exists my_table (
index1 char(32) not null primary key,
title varchar(50),
my_timestamp timestamp not null default current_timestamp on update current_timestamp
)
Any help will be greatly appreciated.
Thanks
First, you need to create code blocks for whatever code you are displaying in your question/answer by highlighting the lines of code and pressing ctrl-k
You will need a trigger that changes the date value in the row to the current date using the CURDATE() function. BEFORE UPDATE simply means apply the current block enclosed in "BEGIN... END" before the actual update call is made by MySQL. You access the row to be updated with NEW.<field>. To store a value in a particular tuple, use the SELECT ... INTO .... statement
DELIMITER $$
CREATE TRIGGER trigger_name
BEFORE UPDATE ON table_name
FOR EACH ROW
BEGIN
SELECT CURDATE() INTO NEW.`col4(date)`;
END $$
DELIMITER ;
For more info, see: https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html
https://dev.mysql.com/doc/refman/8.0/en/ansi-diff-select-into-table.html
UPDATE: YOU CANNOT UPDATE WITHIN AN UPDATE TRIGGER, MySQL does not prevent an update trigger from being called by itself, nor does it prevent deadlock issues, so you cannot use this. Must use the method below.
Using the method described in the comments (if your version supports it):
CREATE TABLE last_mod (
last_modified_date DATE NOT NULL,
PRIMARY KEY (last_modified_date)
)
CREATE TABLE IF NOT EXISTS my_table (
my_date DATETIME NOT NULL,
INDEX par (my_date),
FOREIGN KEY (my_date) REFERENCES last_mod(mast_modified_date) ON UPDATE CASCADE
);
DELIMITER $$
CREATE TRIGGER trigger_name
BEFORE UPDATE ON my_table
FOR EACH ROW
BEGIN
UPDATE last_mod SET last_modified_date = CURDATE();
END $$
DELIMITER ;
Related
In MySQL, I want to fire a trigger when update on all columns except one column update.
In my table row I have 40 columns. I want trigger to update the column update_time whenever there is an update happens on any field except update_time field.
CREATE TRIGGER `UpdateDateTrigger`
BEFORE UPDATE ON `users`
FOR EACH ROW
IF NOT UPDATE(`update_time`) BEGIN
SET new.update_timestamp = now()
END
But it is not working as expected.
By looking at MySQL automatic update for specific column instead of whole record , I've got the solution to exclude two columns update in trigger
IF !((NEW.last_visited <> OLD.last_visited) ||
(NEW.update_time <> OLD.update_time)) THEN
SET new.update_time = now();
END IF
Thank you!
Instead of having a trigger function I would like to suggest you to create the table wisely so that the update_time field gets updated automatically when something is changed associated with that row.
Please look into the documentation here for automatic update on time for each update of the row. The create syntax is simple and effective.
CREATE TABLE t1 (
// .... Other columns
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
If you want a specific control over each of your column, then writing a trigger is the best idea I think. Please check the answer here.
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.
In my schema I had two columns ,I am new to MySQL how to concatenate columns using Computed Column in mysql
ordertbl schema
Autoorderid int auto-increment
Orderid varchar(45)
I want to value orderid value insert when new row inserted
i had created the trigger for but this trigger is not firing when i am inserting the row
insert into order_master(customerID,ItemID,quantity,Unitprice,Total) values ('07961A','1000',6,5,30)
use ntc_sales; DELIMITER
$$ CREATE TRIGGER order_master_BINS BEFORE INSERT ON order_master FOR EACH ROW
SET NEW.OrderID = CONCAT('ORD' ,NEW.AutoOrderID) ; end;
create table
enter code here
CREATE TABLE Demo(ID INT PRIMARY KEY,
IDwithChar AS 'ORD' + RIGHT('0000000' + CAST(ID AS VARCHAR(10)), 6) PERSISTED,valuevar nvarchar(45)
)
This is showing syntax error in mysql how to create table as above schema in mysql
You can't really do this using a trigger in MySQL.
A BEFORE trigger is run before the auto increment value is set, so NEW.AutoOrderID will always be 0.
An AFTER trigger cannot update the same table as it is triggered on.
In other words, instead of triggering on an INSERT, creating the row using a stored procedure that does the insert/update in a single transaction is probably the best way to proceed.
EDIT: You could use a separate table for the sequence, but that would not guarantee that the order number is the same value as AutoOrderID, just a unique value.
CREATE TABLE order_sequence (
seq INT PRIMARY KEY AUTO_INCREMENT
);
CREATE TRIGGER order_master_BINS BEFORE INSERT ON order_master
FOR EACH ROW
BEGIN
INSERT INTO order_sequence VALUES (0);
SET NEW.OrderID = CONCAT('ORD', LAST_INSERT_ID());
END
An SQLfiddle to test the alternate solution with.
I'd like to make a TIMESTAMP field DEFAULT CURRENT_TIMESTAMP, for 'creation time' purpose. But if someone or somehow something changes that TIMESTAMP, my data won't be consistent.
Is there a way I can ensure it won't change unless I delete the row and reinsert it, other than application level?
With the suggested answer provided, i could work around with something like this
CREATE TRIGGER consistency1 BEFORE UPDATE ON table1
FOR EACH ROW
BEGIN
IF NEW.creationtime != OLD.creationtime THEN
SET NEW.creationtime = OLD.creationtime;
END IF;
END;
Since my comment has been appreciated, here's the extended version.
I personally don't think that it's possible.
Anyway, there are a couple of things you can try:
Make sure that only your application can write on the database
Write a trigger like this (pseudocode!)
create trigger prevent_change_timestamp on tbl_name
before update
#fetch old row value
#verify if the timestamp field has been changed
#raise an error (any SQL error will do)
Or like this
create trigger revert_change_timestamp on tbl_name
after update
#fetch pre-change row value
#update the row with the "old" value in place of the new one
I'd personally go with the 3rd option, if possible. Anyway, the 2nd one is good too. I'd not rely on the 1st option unless necessary (eg: no access to trigger functionality)
More info here: reference
It's funny in a way that database apps don't offer this functionality as standard: not only for a "created" timestamp field, but for things like autoincrement id fields, and any miscellaneous values which you may want to set on creating a record and then never allow to be changed... wonder what the rationale is?
What you can do here is, you can write a TRIGGER on the table when a row is being updated. In that trigger, you can compare the old and new values, and if they are different then you can just overwrite the new value with the old one.
I tried this in MySQL 5.1 and got an error
DELIMITER //
CREATE TRIGGER member_update_0
-> AFTER UPDATE ON members
-> FOR EACH ROW
-> BEGIN
-> IF NEW.id != OLD.id THEN
-> SET NEW.id = OLD.id;
-> END IF;
-> END;//
ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger
The same trigger with AFTER replaced by BEFORE is accepted;
to me, this is a counter-intuitive way to do it, but it works
delimiter ;
UPDATE members SET id=11353 WHERE id=1353;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
It is actually possible to do this very neatly if you are using InnoDB.
Create another table with just one column. That column should have a foreign key (hence the innodb requirement in this solution) that points to the immutable column of the original table in question.
Put a restriction like "ON UPDATE RESTRICT".
In summary:
CREATE TABLE original (
....
immutable_column ...
INDEX index1(immutable_column)
....
) ENGINE=INNODB;
CREATE TABLE restricter (
.....
col1,
INDEX index2(col1),
FOREIGN KEY (col1) REFERENCES original (immutable_colum) ON UPDATE RESTRICT ON DELETE CASCADE
) ENGINE=INNODB;
Taking the idea a step further (for those of us still stuck with a legacy version of MySQL) you can have BOTH a protected & defaulted create_stamp AND an auto-updating update_stamp as follows:
If you have a table such as
CREATE TABLE `csv_status` (
`id` int(11) NOT NULL primary key AUTO_INCREMENT,
`create_stamp` datetime not null,
`update_stamp` timestamp default current_timestamp on update current_timestamp,
`status` enum('happy','sad') not null default 'happy'
);
Then you can define these triggers on it
drop trigger if exists set_create_stamp ;
create definer = CURRENT_USER trigger set_create_stamp BEFORE INSERT on
csv_status for each row
set NEW.create_stamp = now();
drop trigger if exists protect_create_stamp ;
delimiter //
create definer = CURRENT_USER trigger protect_create_stamp BEFORE UPDATE on
csv_status for each row
begin
if NEW.create_stamp != OLD.create_stamp then
set NEW.create_stamp = OLD.create_stamp;
end if;
end;//
delimiter ;
Hi I would like to set and forget two fields for tracking the date the record was added and also the date the record was last modified in a mySQL database.
I am using "ON UPDATE CURRENT_TIMESTAMP" and was hoping I would just change UPDATE to INSERT.
No luck however. Can anyone give me the heads up on the best way to achieve this? - preferably inside the database itself.
This assumes MySQL 5. Simply add two triggers:
create table foo (a1 INT, created timestamp, updated timestamp) engine=innodb;
DELIMITER |
CREATE TRIGGER foo_created BEFORE INSERT ON foo
FOR EACH ROW BEGIN
SET new.created := now();
SET new.updated := now();
END;
|
CREATE TRIGGER foo_updated BEFORE UPDATE ON foo
FOR EACH ROW BEGIN
SET new.updated := now();
END;
|
DELIMITER ;
insert into foo (a1) values(7);
select * from foo;
update foo set a1=9;
You basically need both columns to be setup as timestamps with default values of CURRENT_TIMESTAMP. Unfortunately, this is not allowed in MySQL:
Error Code: 1293
Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
You can't have two timestamp columns, even though you need one to only have a default value of CURRENT_TIMESTAMP, and the other one to be UPDATE CURRENT_TIMESTAMP, this is still not allowed.
Your best bet here would be to specify as so:
CREATE TABLE `test` (
`addedDate` dateTime,
`lastModified` timestamp on update CURRENT_TIMESTAMP
)
Unfortunately, you'll have to set the 'addedDate' manually on insert using the NOW() function.
mySQL has a NOW() function you can use, see the tutorial at Tutorials Point that can help you put it in place.
You could add a DATETIME column and set it when you create the row of data. That will serve as the date the record was added.
Next, add a TIMESTAMP column:
Automatic updating of the first TIMESTAMP column in a table occurs under any of the following conditions:
You explicitly set the column to NULL.
The column is not specified explicitly in an INSERT or LOAD DATA INFILE statement.
The column is not specified explicitly in an UPDATE statement and some other column changes value. An UPDATE that sets a column to the value it does not cause the TIMESTAMP column to be updated; if you set a column to its current value, MySQL ignores the update for efficiency.
The TIMESTAMP column will take care of your record modified date.