Custom time in MYSQL on update - mysql

I have a table with some rows and within them there is a definition that goes like this:
`metric_update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
So what i actually want it to do is to automatically insert a timestamp when inserting data into that table. And it does. But what I need is to write a GMT based time into that field (current server time is like GMT+2).
Is there a way to say to MYSQL to do such thing?

If your server time and timezone settings are configured correctly, then internally all times stored in TIMESTAMP columns are converted to GMT (since that's what Unix timestamp mandates). They're converted back to your session timezone when you retrieve this data. If you want it presented in GMT timezone, you need to do conversion while retrieving data not while inserting.
See the console dump below for example. You can run these commands yourself to check.
mysql> use test;
Database changed
mysql> -- let's create a table we'll be working with
mysql> CREATE TABLE tsTable (
-> ID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-> ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-> );
Query OK, 0 rows affected (0.08 sec)
mysql> -- let's check current time as well as timezone settings
mysql> SELECT CURTIME(),##global.time_zone, ##session.time_zone;
+-----------+--------------------+---------------------+
| CURTIME() | ##global.time_zone | ##session.time_zone |
+-----------+--------------------+---------------------+
| 16:25:51 | SYSTEM | +02:00 |
+-----------+--------------------+---------------------+
1 row in set (0.05 sec)
mysql> -- inserting empty row to table to trigger auto timestamp
mysql> INSERT INTO tsTable VALUES (null,null);
Query OK, 1 row affected (0.00 sec)
mysql> -- looks like the time in my local timezone is stored in table
mysql> SELECT * FROM tsTable;
+----+---------------------+
| ID | ts |
+----+---------------------+
| 1 | 2011-07-28 16:26:25 |
+----+---------------------+
1 row in set (0.00 sec)
mysql> -- switching to GMT
mysql> SET SESSION time_zone = '+0:00';
Query OK, 0 rows affected (0.00 sec)
mysql> -- check current time and timezone settings again
mysql> SELECT CURTIME(),##global.time_zone, ##session.time_zone;
+-----------+--------------------+---------------------+
| CURTIME() | ##global.time_zone | ##session.time_zone |
+-----------+--------------------+---------------------+
| 14:27:53 | SYSTEM | +00:00 |
+-----------+--------------------+---------------------+
1 row in set (0.00 sec)
mysql> -- note: CURTIME() returns time two hours 'earlier' than before
mysql> -- let's see what's stored in the table again
mysql> SELECT * FROM tsTable;
+----+---------------------+
| ID | ts |
+----+---------------------+
| 1 | 2011-07-28 14:26:25 |
+----+---------------------+
1 row in set (0.00 sec)
mysql> -- TIMESTAMP is two hours 'earlier' than before too! Magick!

INSERT INTO table_name(column1, metric_update_time) VALUES('dummy', CONVERT_TZ(CURRENT_TIMESTAMP,'+02:00','+03:00');
This will convert the inserted timestamp from GMT+2 to GMT+3.

Related

MySQL convert data type from string to date

Hi all,
I have 2 column in my table (Start Date & End Date), which are actually text. I want to convert them to timestamp format but I'm not sure how to do it. The query below is what I have tried but doesn't work:
ALTER TABLE mytable
MODIFY COLUMN STR_TO_DATE(`Start Date`,"%m/%d/%Y %H:%i") TIMESTAMP,
MODIFY COLUMN STR_TO_DATE(`End Date`,"%m/%d/%Y %H:%i") TIMESTAMP;
May I know how should I alter the data type for these 2 columns in my table? Any help or advise will be greatly appreciated!
Let's say this is our initial column definition state:
mysql> SHOW CREATE TABLE mytable;
+---------+------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+------------------------------------------------------------------------------------------------------------------------------------+
| mytable | CREATE TABLE `mytable` (
`Start_Date` text,
`End_Date` text
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
First you need to use update :
UPDATE mytable SET End_Date = STR_TO_DATE(End_Date,'%m/%d/%Y %H:%i');
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> SELECT * FROM mytable;
+---------------------+---------------------+
| Start_Date | End_Date |
+---------------------+---------------------+
| 2022-10-16 10:35:00 | 2022-10-16 10:40:00 |
| 2022-10-16 09:18:00 | 2022-10-16 09:25:00 |
+---------------------+---------------------+
2 rows in set (0.00 sec)
Then Alter table to change column data type to 'timestamp':
mysql> ALTER TABLE mytable MODIFY COLUMN Start_Date TIMESTAMP, MODIFY COLUMN End_Date TIMESTAMP;
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
If we test it,
mysql> SHOW CREATE TABLE mytable;
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mytable | CREATE TABLE `mytable` (
`Start_Date` timestamp NULL DEFAULT NULL,
`End_Date` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

MySQL datetime error when trying to insert value into table

I get the following error when I try to insert the datetime value in a timestamp field in my MySQL table. I am trying to do this by running a Python code.
_mysql_exceptions.OperationalError: (1292, "Incorrect datetime value: '2018-03-26 10:59:27+00:00' for column 'timestamp' at row 1")
Is there a workaround or a solution to this error ?
2018-03-26 10:59:27+00:00
This is a valid iso-8601 datetime value, but it is not a valid MySQL datetime literal. On that point, the developer is incorrect.
The documentation explains what ALLOW_INVALID_DATES does:
Check only that the month is in the range from 1 to 12 and the day is in the range from 1 to 31.
In other words, 2018-03-26 would be a permissible date if allow_invalid_dates is set. This option does not do anything when the date or datetime isn't even in a valid format for MySQL.
The +00:00 is the timezone offset from UTC. In this case, the time expressed is in UTC, so the offset is zero hours, zero minutes.
Your workaround would be to remove the STRICT_TRANS_TABLES from the sql_mode that is a default in the config file created during the MySQL 5.6 installation process... you need to carefully consider the implications of changing this, but it does allow the data to go in.
mysql> select ##sql_mode;
+--------------------------------------------+
| ##sql_mode |
+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
1 row in set (0.00 sec)
mysql> insert into datetimetest(dt) values ('2018-03-26 10:59:27+00:00');
ERROR 1292 (22007): Incorrect datetime value: '2018-03-26 10:59:27+00:00' for column 'dt' at row 1
-- remove STRICT_TRANS_TABLES -- note that executing this only removes it for your
-- current session -- it does not make a server-wide config change
mysql> set ##sql_mode='no_engine_substitution';
Query OK, 0 rows affected (0.00 sec)
mysql> select ##sql_mode;
+------------------------+
| ##sql_mode |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+
1 row in set (0.00 sec)
-- now MySQL will accept the invalid value, with a warning
mysql> insert into datetimetest(dt) values ('2018-03-26 10:59:27+00:00');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+-----------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------+
| Warning | 1265 | Data truncated for column 'dt' at row 1 |
+---------+------+-----------------------------------------+
1 row in set (0.00 sec)
-- the value did get inserted, but the time zone information was lost:
mysql> select * from datetimetest;
+----+---------------------+
| id | dt |
+----+---------------------+
| 1 | 2013-08-26 12:00:00 |
+----+---------------------+
1 row in set (0.00 sec)

MYSQL CURRENT_TIMESTAMP only applied on update

I have a database with a column named date (timestamp) which is set to default CURRENT_TIMESTAMP. This used to work fine, however after migrating the database to a different server the timestamp only gets applied after an UPDATE query is performed, an INSERT query just sets it to "0000-00-00 00:00:00".
I suspect that whatever is doing the insert is putting an empty string into the field. Look at this result;
MariaDB [horizon]> create table foo (t timestamp default current_timestamp not null);
Query OK, 0 rows affected (0.02 sec)
MariaDB [horizon]> insert into foo values ('');
Query OK, 1 row affected, 1 warning (0.01 sec)
MariaDB [horizon]> select * from foo;
+---------------------+
| t |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)
I would check the code that is doing the insert - if it's coming from a web form the form itself could be submitting an empty string. You really need to insert null or leave the column out of the INSERT to get the default.
MariaDB [horizon]> insert into foo values (null);
Query OK, 1 row affected (0.01 sec)
MariaDB [horizon]> insert into foo values ();
Query OK, 1 row affected (0.00 sec)
MariaDB [horizon]> select * from foo;
+---------------------+
| t |
+---------------------+
| 0000-00-00 00:00:00 |
| 2017-09-19 21:41:16 |
| 2017-09-19 21:41:20 |
+---------------------+
3 rows in set (0.00 sec)

Truncated incorrect date value: '02:02:02 am'

When i insert this time '02:02:02 am' to a mysql time field using the following Query:
insert INTO invoices(name,phone,totalsum,givenmoney,date,time,moreinfo) VALUES ('f','2','2','2','1994-01-01',DATE_FORMAT('02:02:02 am','%h:%i:%s %p'),'AA')
It shows the following error
Truncated incorrect date value: '02:02:02 am'
how to solve it?
Not that the datatype of my time field is TIMESTAMP
You are close but you should use str_to_time instead
mysql> select str_to_date('02:02:02 am','%h:%i:%s %p');
+------------------------------------------+
| str_to_date('02:02:02 am','%h:%i:%s %p') |
+------------------------------------------+
| 02:02:02 |
+------------------------------------------+
1 row in set (0.00 sec)
Instead of timestamp I would suggest to use time data type for storing the time value H:i:s format http://dev.mysql.com/doc/refman/5.7/en/time.html
UPDATE :
Getting some error while running the query by SO
Here is a test case ran on mysql 5.5
mysql> create table invoices (
-> name varchar(30),
-> phone varchar(30),
-> totalsum varchar(30),
-> givenmoney varchar(30),
-> date date,
-> time time,
-> moreinfo varchar(30)
-> );
Query OK, 0 rows affected (0.13 sec)
mysql>
mysql> insert INTO invoices
-> (name,phone,totalsum,givenmoney,date,time,moreinfo)
-> VALUES
-> ('f','2','2','2','1994-01-01',str_to_date('02:02:02 am','%h:%i:%s %p'),'AA');
Query OK, 1 row affected (0.04 sec)
mysql> select * from invoices ;
+------+-------+----------+------------+------------+----------+----------+
| name | phone | totalsum | givenmoney | date | time | moreinfo |
+------+-------+----------+------------+------------+----------+----------+
| f | 2 | 2 | 2 | 1994-01-01 | 02:02:02 | AA |
+------+-------+----------+------------+------------+----------+----------+
1 row in set (0.00 sec)
for 5.6 here is the fiddle http://sqlfiddle.com/#!9/79e0c9/1

Is it possible to configure MySQL to return TIMESTAMP value as a UNIXTIMESTAMP?

Is it possible to configure MySQL to return TIMESTAMP value as a UNIXTIMESTAMP by default, rather than casting every column in the SELECT statement?
MySQL has a function to convert a date to a unix timestamp.
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_unix-timestamp
mysql> SELECT UNIX_TIMESTAMP();
-> 1196440210
mysql> SELECT UNIX_TIMESTAMP('2007-11-30 10:30:19');
-> 1196440219
You cannot do that in MySQL configuration.
You can do that on application level - e.g. in PHP, you can use the mysqli_result::fetch_fields() method to detect timestamp type and convert it, other connectors will have similar methods.
Or you can do it - as suggested - using UNIX_TIMESTAMP() function on timestamp columns.
It sounds as though you want a different view of the same data:
mysql> select * from t;
+------+---------------------+
| data | ts |
+------+---------------------+
| foo | 2013-03-19 16:54:45 |
+------+---------------------+
1 row in set (0.00 sec)
mysql> select data, unix_timestamp(ts) from t;
+------+--------------------+
| data | unix_timestamp(ts) |
+------+--------------------+
| foo | 1363712085 |
+------+--------------------+
1 row in set (0.00 sec)
mysql> create view tv (data, time_t) as select data, unix_timestamp(ts) from t;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from tv;
+------+------------+
| data | time_t |
+------+------------+
| foo | 1363712085 |
+------+------------+
1 row in set (0.00 sec)