I'm adding a column tsu (timestamp update) of type DATETIME to a number of my tables.
I need to write BEFORE UPDATE triggers that will update the column to CURRENT_TIMESTAMP(), but I can't get it right. Tried:
DELIMITER $$
CREATE
TRIGGER `cams`.`tsu_update_csi` BEFORE UPDATE
ON `cams`.`csi`
FOR EACH ROW BEGIN
UPDATE csi SET tsu = CURRENT_TIMESTAMP WHERE csi_code = OLD.csi_code;
END$$
DELIMITER ;
Can anyone point me in the right direction pls?
MTIA
Okay, try this one:
DELIMITER $$ CREATE
TRIGGER `cams`.`tsu_update_csi` BEFORE UPDATE
ON `cams`.`csi`
FOR EACH ROW BEGIN
SET NEW.tsu = CURRENT_TIMESTAMP;
END$$ DELIMITER ;
If the field can be defined as a timestamp, you can use the following:
ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP);
Don't know if it'll work for you, but you can always make it a TIMESTAMP field with no default value -- MySQL will automatically set the value of the first such field defined in the table to the current timestamp on every update.
ts2 CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP works for DATETIME and TIMESTAMP fields, for one and multiple fields
so you can use datecreated CURRENT_TIMESTAMP (as the default value)
and dateupdated CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP works for DATETIME and TIMESTAMP fields (as the default value)
You can use the above as SQL commands or default values in MySQL workbench
There are a lot of non-working or incomprehensible examples on the network.
I spent several hours to put together a working example for my EFFCORE CMS.
Here is this example:
Trigger on UPDATE
DELIMITER ;;
CREATE TRIGGER `updated_at__on_update`
BEFORE UPDATE
ON `demo`
FOR EACH ROW
BEGIN
SET new.updated_at = UNIX_TIMESTAMP();
END;;
DELIMITER ;
Trigger on INSERT
DELIMITER ;;
CREATE TRIGGER `updated_at__on_insert`
BEFORE INSERT
ON `demo`
FOR EACH ROW
BEGIN
SET new.updated_at = UNIX_TIMESTAMP();
END;;
DELIMITER ;
Table demo
CREATE TABLE `demo` (
`id` int NOT NULL AUTO_INCREMENT,
`text` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`updated_at` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
);
Related
I've created a table in mySQL like this:
CREATE TABLE IF NOT EXISTS `LibraryManager`.`Card` (
`card_id` INT NOT NULL AUTO_INCREMENT,
`card_registerDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`card_expiredDate` TIMESTAMP,
PRIMARY KEY (`card_id`))
ENGINE = InnoDB;
Now I want to set the default value of card_expiredDate to card_registerDate + 30 or CURRENT_TIMESTAMP + 30 (30 day from register date). Is there any way to do that?
Thank you very much for reading this.
Setting the default value for expiry column using create statement is not possible as such, instead use trigger. For that you will have to slightly modify you create statement. Just change the datatype of expiry column, your new query:
CREATE TABLE IF NOT EXISTS `LibraryManager`.`Card` (
`card_id` INT NOT NULL AUTO_INCREMENT,
`card_registerDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`card_expiredDate` DATETIME,
PRIMARY KEY (`card_id`))
ENGINE = InnoDB;
and then fire the following trigger
CREATE TRIGGER before_insert_library_card
BEFORE INSERT ON `LibraryManager`.`Card`
FOR EACH ROW
SET new.card_expiredDate = adddate(CURRENT_TIMESTAMP,30);
hope this helps.
P.S: Triggers slow down your insert operations(or whatever operation they are applied before/after). I suggest you set these values programmatically using php/python or whatever the backend you are using.
Related:
Can I use a function for a default value in MySql?
Create an AFTER INSERT trigger, it will do the job for you:
DELIMITER $$
CREATE TRIGGER set_expiration_date
AFTER INSERT ON `LibraryManager` FOR EACH ROW
BEGIN
UPDATE LibraryManager
SET card_expiredDate = DATE_ADD(NEW.card_registerDate, INTERVAL 30 DAY)
WHERE card_id = NEW.card_id;
END;
$$
DELIMITER ;
PS: I haven't tested it, if you get any error do let me know.
I have this MySQL table:
create table test.customer (
ID INTEGER,
CREATION_TIME DATETIME,
CREATION_USER VARCHAR(50),
CHANGE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CHANGE_USER VARCHAR(50),
PRIMARY KEY(ID)
);
I want to automatically set the user & timestamps for logging purpose. I do have one trigger before insert (actually written only for the creation_time):
delimiter #
create trigger test.customer_creation
before insert on test.customer
for each row
begin
set NEW.CREATION_TIME = NOW();
IF (NEW.CREATION_USER is null or NEW.CREATION_USER = '')
THEN set NEW.CREATION_USER = USER();
end IF;
end #
delimiter ;
but I don't really want a trigger just for the CHANGE_USER. Is there a possibility to set the CHANGE_USER with something like: DEFAULT USER()? or do I have to create a additional trigger?
In MySQL you simply can't use a function as a default value for a column, you can use
the keywords: NULL, CURRENT_TIMESTAMP and localtimestamp, while you can't use functions(except for now() that is internally represented as a synonym of CURRENT_TIMESTAMP).
So in your case the way to follow is the trigger ON insert ... You need the additional trigger .
Is there any way to set the default value for a column as an expire date (some hours from CURRENT_TIMESTAMP)?
I have already tried:
ALTER TABLE `table`
ADD COLUMN `expire` TIMESTAMP NOT NULL DEFAULT TIMESTAMPADD(HOUR, 5, CURRENT_TIMESTAMP);
But didn't work..
You can't implement a complex default value like that in the table definition.
You can do it with a trigger if you want:
DELIMITER $$
DROP TRIGGER IF EXISTS tr_b_ins_table $$
CREATE TRIGGER tr_b_ins_table BEFORE INSERT ON table FOR EACH ROW BEGIN
SET NEW.expire = NOW() + INTERVAL 5 HOUR;
END $$
DELIMITER ;
I have table as shown below. In order to workaround one default now column restriction of MySQL I used the tip as shown here
CREATE TABLE IF NOT EXISTS mytable (
id INT NOT NULL AUTO_INCREMENT ,
create_date TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00' ,
update_date TIMESTAMP NULL DEFAULT NOW() ON UPDATE NOW() ,
PRIMARY KEY (`parti_id`) )
ENGINE = InnoDB;
My sql_mode does not include NO_ZERO_DATE as pointed here my output :
mysql> SELECT ##sql_mode;
+------------+
| ##sql_mode |
+------------+
| |
+------------+
1 row in set (0.00 sec)
It is still giving the error as shown below:
ERROR 1067 (42000) at line xx in file: '/myschema.sql': Invalid default value for 'create_date'
I use MySQL 5.1.37 on Ubuntu
How can I fix it? Thanks.
You can only have one timestamp column that defaults to CURRENT_TIMESTAMP or NOW() per table. This is a well known bug in MySQL.
To overcome this, make your default for the created column a valid timestamp value, then insert the timestamp in your CRUD application code.
Use NOW() or CURRENT_TIMESTAMP for your updated column default.
Reference material:
http://dev.mysql.com/doc/refman/5.1/en/timestamp.html
To further illustrate MySQL's shortcoming in this area, consider the following code:
CREATE TABLE testing_timestamps (
id INT NOT NULL AUTO_INCREMENT,
pk_id INT NOT NULL,
col1 TIMESTAMP DEFAULT 0,
col2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(id)
);
delimiter $$
CREATE TRIGGER testing_timestamps_trigger
AFTER INSERT ON testing_timestamps
FOR EACH ROW
BEGIN
UPDATE testing_timestamps SET col1 = NOW() WHERE id = MAX(id);
END;
$$
delimiter ;
INSERT INTO testing_timestamps (id) VALUES (0);
The output from this will display:
mysql> INSERT INTO testing_timestamps (id) VALUES (0);
ERROR 1442 (HY000): Can't update table 'testing_timestamps' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
This is a bummer because using a trigger in this instance would be a good work around.
Actually, Randy's code is broken. It won't work because it is a mutating trigger. You can't update the table that initiated the updating. For example, if you are updating the table SESSIONS, you can't the go modify the table in your trigger using an UPDATE, INSERT or DELETE statement. The only way you are allowed to modify the table to which the trigger is attached is to use the "NEW" or "OLD" prefixes as demonstrated below. (Of course, you are allowed to update other tables at will.) Here is an example of how to overcome the problem described by the op.
create table sessions (
id integer not null,
created timestamp not null default 0,
updated timestamp not null default 0
);
delimiter //
create trigger bifer_sessions_ts before insert on sessions for each row
begin
set new.created = now();
set new.updated = now();
end;
//
create trigger bufer_sessions_ts before update on sessions for each row
begin
set new.updated = now();
end;
//
delimiter ;
To do this and have it work:
col1 TIMESTAMP DEFAULT 0,
col2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
You don't need a trigger for col1, just ensure the value is NULL in your query. The answer is in the certification guide.
Default TIMESTAMP is not supported in MySQL before versions 5.6.1 in the same table.
After version MySQL 5.6.+ it allows two or more TIMESTAMP columns in same table.
You can try updating your mysql version
How can I setup a MySql schema with a DateTime column such that its value will always be the time of the last insert/update to this row?
You can the TIMESTAMP instead and set the ON UPDATE CURRENT_TIMESTAMP NOT NULL, for example:
CREATE TABLE example (
lastUpdate TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL
);
Anax was close, but missed the default value.
CREATE TABLE example (
lastUpdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL
)
Like Anax said, using TIMESTAMP instead of DATETIME will give you a column that uses the current time instead of waiting for a provided date/time.
You have a lot of options with TIMESTAMP, the two that are most important are:
Having it use the current time ( NOW() ) when the row is created,
Having it modify the column to the current time when the row is modified.
If you don't set any options, like so:
CREATE TABLE stuff (ts TIMESTAMP);
It will put in the current time on creation and change that column on modification.
So if you want a column that only shows when it was created, you would use:
CREATE TABLE stuff (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Since you have not specified an ON UPDATE clause, it will not do anything if the row is updated.
If you are insane, like me, you'll want both, and go with:
CREATE TABLE stuff (create_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
mod_date TIMESTAMP
);
and since I haven't written this out yet, that last one is equivalent to writing out:
CREATE TABLE stuff (create_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
mod_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
You could do it with triggers:
DELIMITER $$
CREATE TRIGGER `before_update` BEFORE UPDATE ON `table_name` FOR EACH ROW BEGIN
SET NEW.update_date = NOW();
END;
$$
CREATE TRIGGER `before_insert` BEFORE INSERT ON `table_name` FOR EACH ROW BEGIN
SET NEW.update_date = NOW();
END;
$$
DELIMITER ;