How to set DEFAULT ON UPDATE CURRENT_TIMESTAMP + 5 MINUTES? - mysql

I have a table with three columns:
"code" column (integers)
two DATETIME columns ("created_at", "expires_at")
"created_at" column default value is CURRENT_TIMESTAMP.
"expires_at" column default value is CURRENT_TIMESTAMP + INTERVAL 5 MINUTE.
So far no problem.
Now I would like the ON UPDATE values to be the same as the default ones:
for the "created_at" column, ON UPDATE CURRENT_TIMESTAMP works like a charm.
for the "expires_at" column, I can't get ON UPDATE (CURRENT_TIMESTAMP + INTERVAL 5 MINUTE)
The query to create the "expires_at" column
ALTER TABLE codes ADD expires_at DATETIME DEFAULT (CURRENT_TIMESTAMP + INTERVAL 5 MINUTE);
work successfully.
When I try to add ON UPDATE,
ALTER TABLE codes ADD expires_at DATETIME DEFAULT (CURRENT_TIMESTAMP + INTERVAL 5 MINUTE) ON UPDATE (CURRENT_TIMESTAMP + INTERVAL 5 MINUTE);
this query doesn't work.
It returns the error: ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(CURRENT_TIMESTAMP + INTERVAL 5 MINUTE)' at line 1
I also tried with:
NOW() instead of CURRENT_TIMESTAMP
DATE_ADD() and ADDTIME() functions
but these solutions also do not work.

Such expression in ON UPDATE is not allowed. You may use intermediate updated_at column and generated expired_at column.
DEMO
CREATE TABLE test (
id INT PRIMARY KEY,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
expired_at DATETIME GENERATED ALWAYS AS (updated_at + INTERVAL 3 MINUTE)
);
INSERT INTO test (id) VALUES (1);
SELECT *, SLEEP(2) FROM test;
id
created_at
updated_at
expired_at
SLEEP(2)
1
2023-01-06 14:00:35
2023-01-06 14:00:35
2023-01-06 14:03:35
0
UPDATE test SET id = 2 WHERE id = 1;
SELECT * FROM test;
id
created_at
updated_at
expired_at
2
2023-01-06 14:00:35
2023-01-06 14:00:37
2023-01-06 14:03:37
fiddle

Related

Create table and set default value to NOW() + 24 hours

I'm trying to create a table and set the default value to now() + 24 hours. I'm getting syntax errors when trying to do this.
This doesn't work
CREATE TABLE IF NOT EXISTS `my_table` (
`my_table_id` CHAR(36) BINARY NOT NULL ,
`expiration_time` DATETIME NOT NULL DEFAULT (NOW() + INTERVAL 24 HOUR),
PRIMARY KEY (`my_table_id`)
) ENGINE=InnoDB;
Although this does work SELECT NOW() + INTERVAL 24 HOUR; so i'm not sure why it doesn't work when trying to create a table.
Expressions for defaults are not supported in MySQL 5.7.
You can implement a "default" expression in a trigger such as the following:
CREATE TRIGGER my_awesome_trigger BEFORE INSERT ON my_table
FOR EACH ROW
SET NEW.expiration_time = COALESCE(NEW.expiration_time, NOW() + INTERVAL 24 HOUR));

How to find last row that ran NULLIF() or has null in mysql?

I currently run this operation to convert empty strings to null. Is any way to find out the last row that has gone through NULLIF() operation or has null character so I can process everything from that point. My table has a timestamp column. I have 150 columns like recovery_email and I'd like to start from the last empty string was found in either of them.
UPDATE table
SET recovery_email = NULLIF(recovery_email, ''), # There are 150 columns like recovery_email.
email = NULLIF(email, ''),
WHERE timestamp >= (NOW() - INTERVAL 1 DAY)
If none of your recovery_email is null before the update query is executed, you can run the following query after the update statement to get the timestamp of the last updated row:
select max(timestamp) last_timestamp
from mytable
where recovery_email is null and timestamp >= now() - interval 1 day
Otherwise, you need to compute the latest value before the update, with the following query:
select max(timestamp) last_timestamp
from mytable
where recovery_email = '' and timestamp >= now() - interval 1 day
This answers the original version of the question.
Why would you use NULLIF()? Just filter down to the rows you want:
UPDATE table
SET recovery_email = NULL
WHERE timestamp >= (NOW() - INTERVAL 1 DAY) AND recovery_email = '';
You can put an index on recovery_email and not worry about attempting to filter by time.
Or, better yet, defined the column with a check constraint (in the most recent versions of MySQL) so empty strings are not allowed.

Timestamp comparison doesn't work on TIMESTAMP field

I have a database column called time
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
But when I run the following query using PDO:
DELETE FROM `table` WHERE time < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL :days DAY))
It throws the following exception:
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '1555980012' for column 'time' at row 1
I don't understand why this is happening, could any one please explain?
You do not need to use UNIX_TIMESTAMP function in your where clause to convert date to number.
This should work with no issue:
DELETE FROM `table` WHERE `time` < DATE_SUB(NOW(), INTERVAL :days DAY)

How can I implement a massive update query that add n days to the date section of a DateTime field?

I am not so into DB and I have the following problem that I don't know how can be done in a smart way. I am woring using MySql
I have this MeteoForecast table:
CREATE TABLE MeteoForecast (
id BigInt(20) NOT NULL AUTO_INCREMENT,
localization_id BigInt(20) NOT NULL,
seasonal_forecast_id BigInt(20),
meteo_warning_id BigInt(20),
meteo_forecast_status_id BigInt(20),
start_date DateTime NOT NULL,
end_date DateTime NOT NULL,
min_temp TinyInt(4),
max_temp TinyInt(4),
icon_link VarChar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
chances_of_rain TinyInt(11),
wind TinyInt(1),
humidity TinyInt(11),
PRIMARY KEY (
id
)
) ENGINE=InnoDB AUTO_INCREMENT=1872 ROW_FORMAT=DYNAMIC DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
ALTER TABLE MeteoForecast COMMENT = '';
Each record of this table represents a weather forecast.
At the moment contains some mocked test data that have to be massively update.
As you can see this table contains these 2 DateTime fields: start_date and end_date containing a forecast timeframe.
These field are DateTime because the timeframe is something like this:
start_date = 31/05/2018 12:00:00
end_date = 31/05/2018 18:00:00
The problem is that I have a lot of records that after some times expires (because the days pass and these forecast are in the past...).
I want to do a massive update that change only the date section of the start_date and end_date fields of every record in my DB.
The problem is that I can't use a fixed date to do the update but I have to do something like this:
take the date section of the start_date/end_date field of the record that is updating and add 10 days.
So considering the previous example:
start_date = 31/05/2018 12:00:00
end_date = 31/05/2018 18:00:00
have to become something like:
start_date = 10/06/2018 12:00:00
end_date = 31/06/2018 18:00:00
How can I implement a massive update query doing something like this?
I want to do a massive update that change only the date section of the
start_date and end_date fields of every record in my DB.
The problem is that I can't use a fixed date to do the update but I
have to do something like this:
take the date section of the start_date/end_date field of the record
that is updating and add 10 days.
You need to have a UPDATE query without WHERE clause to update every record in the database.
This query will add 10 days to the existing data within the colums start_date and end_daye
UPDATE
MeteoForecast
SET
MeteoForecast.start_date = MeteoForecast.start_date + INTERVAL 10 DAY
, MeteoForecast.end_date = MeteoForecast.end_date + INTERVAL 10 DAY
If you want update start_date and add 10 days you can do:
UPDATE MeteoForecast SET start_date = start_date + INTERVAL 10 DAY;
For end_date if you want the last day of the month use the function LAST_DAY will return the last day of the month:
UPDATE MeteoForecast SET end_date = LAST_DAY(start_date);
You can use addtime():
update MeteoForecast
set start_date = addtime(cast('2018-06-10' as datetime), time(start_date)),
end_date = addtime(cast('2018-06-10' as datetime), time(end_date));
We can use DATE_ADD() function for this
UPDATE MeteoForecast SET start_date = DATE_ADD(start_date, INTERVAL 10 DAY) , end_date = DATE_ADD(end_date, INTERVAL 10 DAY)

MySQL date interval on select

i've made this SQL code :
CREATE TABLE `logs` (
`id_log` INT(11) NOT NULL AUTO_INCREMENT,
`data_log` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id_log`),
)
i made it to Insert a record when my server goes down,but i would like to make some check if it wasn't Inserted the same record 10 minutes before.
So i was looking for some SELECT that shows only records from NOW() to 10 minutes before.
You're looking for INTERVAL # [UNIT], there's various ways to use it -- http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html:
SELECT count(*)
FROM logs
WHERE data_log > NOW() - INTERVAL 10 MINUTE;
This will return the count of records written to the log in the last ten minutes:
SELECT Count(*) as count_in_last_10 FROM logs WHERE data_log BETWEEN DATE(NOW()-INTERVAL 10 MINUTE) AND NOW()