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

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

Related

mysql date_format is not working returning empty

I am having problem while getting the result i want from database, DATE_FORMAT function is returning null instead or returning a formatted date.
table columns and their datatype:
paid_amount -> float
created_at -> varchar(100)
bellow is the query is:
SELECT SUM(paid_amount) AS amount,
date_format(created_at,'%Y-%m-%d') as dated
FROM `job_card`
WHERE date_format(created_at,'%Y-%m-%d') >= '2017-09-03' AND
date_format(created_at,'%Y-%m-%d') <= '2017-10-03' GROUP BY date(created_at)
I am using another approach of converting date to time stamp using UNIX_TIMESTAMP function but the still getting the same issue:
SELECT SUM(paid_amount) AS paid_amount,
UNIX_TIMESTAMP(created_at) AS duration
FROM job_card
WHERE UNIX_TIMESTAMP(created_at) >= 1504549800 AND
UNIX_TIMESTAMP(created_at) <= 1507055400 GROUP BY date(payment_date)
You can't use the date functions on a varchar field. You'll need to convert created_at to a date field.
That will make your SQL a lot cleaner as well as you can just use clauses like created_at > '2017-09-03' directly in your query.
I don't know how your dates are formatted currently as strings, but your best bet is probably to write something to read the dates out, format them as YYYY-MM-DD, and re-insert them. If all the dates are that format you should be able to convert that field to date type and keep the information intact.
mysql> desc test;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| field1 | varchar(10) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> select * from test;
+------------+
| field1 |
+------------+
| 2017-01-01 |
+------------+
1 row in set (0.00 sec)
mysql> alter table test modify field1 date;
Query OK, 1 row affected (0.24 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> desc test;
+--------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------+------+-----+---------+-------+
| field1 | date | YES | | NULL | |
+--------+------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> select * from test;
+------------+
| field1 |
+------------+
| 2017-01-01 |
+------------+
1 row in set (0.00 sec)

MYSQL: DATE function returning null in Select query

i have a data with all column types as text even date also stored in text type column. Now when i am using select query to access the column its working find but when i am trying to perform any date operation on that column it always return null.
Table:
if am running query select column_14 from mytable where id = 2 its working fine but when i am trying to find the difference between today date and column_14 its always return null
Query Running:
select DATEDIFF(NOW(),STR_TO_DATE(column_14,"%y-%m-%d")) from `mytable` where id = 2
can anyone please tell me what is wrong in my query ?
Structure View
It should be %Y instead of %y. %Y takes 4 digit year.
DATEDIFF(NOW(),STR_TO_DATE(column_14,"%Y-%m-%d"))
Str_to_date will return null values if you pick the wrong format or the function detects an out of range month or day number. In your example you have picked a wrong format %y should be %Y. Here are some samples of what can happen. (nb: str_to_date is poor at this and doesn't check how many days are valid for a month)
MariaDB [sandbox]> create table t (dt text);
Query OK, 0 rows affected (0.28 sec)
MariaDB [sandbox]> insert into t values ('2017-13-01'),('2017-04-31'),('2017-04-33'),('2017-04-03'),('birth_date');
Query OK, 5 rows affected (0.02 sec)
Records: 5 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select str_to_date(dt,'%y-%m-%d') Invalid_year_format,
-> str_to_date(dt,'%Y-%m-%d') Valid_year_format_MM_and_DD,
-> datediff(now(),str_to_date(dt,'%Y-%m-%d')) datediff_examples
-> from t;
+---------------------+-----------------------------+-------------------+
| Invalid_year_format | Valid_year_format_MM_and_DD | datediff_examples |
+---------------------+-----------------------------+-------------------+
| NULL | NULL | NULL |
| NULL | 2017-04-31 | -6 |
| NULL | NULL | NULL |
| NULL | 2017-04-03 | 22 |
| NULL | NULL | NULL |
+---------------------+-----------------------------+-------------------+
5 rows in set, 11 warnings (0.00 sec)

What is the true range of possible values of a field type 'DATE'?

DATE field type has limitations '1000-01-01' -'9999-12-31'.
BUT Why inserted '987-10-10' not '1000-01-01' ?
mysql> INSERT INTO DATE12(datas) VALUES('987-10-10');
Query OK, 1 row affected (0.03 sec)
mysql> SELECT * FROM DATE12;
+------+------------+
| id | datas |
+------+------------+
| NULL | 1987-11-04 |
| NULL | 0987-10-10 |
+------+------------+
2 rows in set (0.00 sec)
incorrect data format
mysql> INSERT INTO DATE12(datas) VALUES('10001-13-12');
Query OK, 1 row affected, 1 warning (0.03 sec)
mysql> SELECT * FROM DATE12;
+------+------------+
| id | datas |
+------+------------+
| NULL | 1987-11-04 |
| NULL | 0987-10-10 |
| NULL | 0000-00-00 |
But for time type all good
mysql> INSERT INTO time1(t) VALUE('-1112:45:12');
Query OK, 1 row affected, 1 warning (0.02 sec)
mysql> SELECT * FROM time1;
+------+------------+
| id | t |
+------+------------+
| NULL | NULL |
| NULL | -12:45:12 |
| NULL | -838:59:59 |
+------+------------+
3 rows in set (0.00 sec)
mysql> INSERT INTO time1(t) VALUE('11112:45:12');
Query OK, 1 row affected, 1 warning (0.02 sec)
mysql> SELECT * FROM time1;
+------+------------+
| id | t |
+------+------------+
| NULL | NULL |
| NULL | -12:45:12 |
| NULL | -838:59:59 |
| NULL | 838:59:59 |
+------+------------+
4 rows in set (0.00 sec)
mysql>
...Why insered '987-10-10' not '1000-01-01' ?
As per documentation on The DATE, DATETIME, and TIMESTAMP Types
For the DATE and DATETIME range descriptions, “supported” means that although earlier values might work, there is no guarantee.
Meaning, the dates prior to '1000-01-01' may also be accepted, but not guaranteed.
And hence, in your case the date entry '987-10-10' is accepted with no errors.
And you claim that '1000-01-01' is not inserted. But you actually tried '10001-13-12'.
And even if you try with '1000-13-12', it will fail, because, value '13' for 'month' part is meaning less.
As per documentation on Date and Time Literals
As a string with no delimiters in either 'YYYYMMDD' or 'YYMMDD' format, provided that the string makes sense as a date. For example, '20070523' and '070523' are interpreted as '2007-05-23', but '071332' is illegal (it has nonsensical month and day parts) and becomes '0000-00-00'.
Though not seen in the documentation, the above statement is also valid for format like 'YYYY-MM-DD' and others. And the same is shown in the following example:
mysql> insert into vdt(dt) values( '1001-13-32' );
ERROR 1292 (22007): Incorrect date value: '1001-13-32' for column 'dt' at row 1
mysql> select date_format( '2013-13-32', '%Y-%m-%d' ); show warnings;
+-----------------------------------------+
| date_format( '2013-13-32', '%Y-%m-%d' ) |
+-----------------------------------------+
| NULL |
+-----------------------------------------+
1 row in set, 1 warning (0.00 sec)
+---------+------+----------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------+
| Warning | 1292 | Incorrect datetime value: '2013-13-32' |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)
mysql> select str_to_date( '20131232', '%Y%m%d' ); show warnings;
+-------------------------------------+
| str_to_date( '20131232', '%Y%m%d' ) |
+-------------------------------------+
| NULL |
+-------------------------------------+
1 row in set, 1 warning (0.00 sec)
+---------+------+---------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------+
| Warning | 1411 | Incorrect datetime value: '20131232' for function str_to_date |
+---------+------+---------------------------------------------------------------+

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)

Date reverts to 2000-01-01 from ActiveRecord to MySQL

I am trying to save a time in a MySQL table. However, the date reverts to 2000-01-01.
1.9.2p320 :036 > vv = Visitor.new
=> #<Visitor id: nil, ip_address: nil, num_day_visits: nil, last_visit: nil>
1.9.2p320 :037 > vv.last_visit = Time.now; vv.ip_address = "3.3.3.3"
=> "3.3.3.3"
1.9.2p320 :038 > vv.num_day_visits = 1
=> 1
1.9.2p320 :039 > vv
=> #<Visitor id: nil, ip_address: "3.3.3.3", num_day_visits: 1, last_visit: "2012-10-11 01:31:04">
1.9.2p320 :040 > vv.save
SQL (0.2ms) BEGIN
SQL (0.7ms) INSERT INTO `visitors` (`ip_address`, `last_visit`, `num_day_visits`) VALUES (?, ?, ?) [["ip_address", "3.3.3.3"], ["last_visit", 2012-10-11 01:31:04 -0400], ["num_day_visits", 1]]
(0.5ms) COMMIT
=> true
1.9.2p320 :042 > vv
=> #<Visitor id: 1199, ip_address: "3.3.3.3", num_day_visits: 1, last_visit: "2012-10-11 01:31:04">
1.9.2p320 :043 > Visitor.find(:all,:conditions=>{:ip_address => "3.3.3.3"})
Visitor Load (1.4ms) SELECT `visitors`.* FROM `visitors` WHERE `visitors`.`ip_address` = '3.3.3.3'
=> [#<Visitor id: 1199, ip_address: "3.3.3.3", num_day_visits: 1, last_visit: "2000-01-01 05:31:04">]
So when I retrieve the record, the date is 2000-01-01.
The table in MySQL:
mysql> describe visitors ;
+----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ip_address | varchar(255) | NO | | NULL | |
| num_day_visits | int(11) | NO | | NULL | |
| last_visit | time | NO | | NULL | |
+----------------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
Update: I created a toy table to play around the conversion from time to datetime. This is what happens:
mysql> select * from example ;
+----+----------+
| id | mytime |
+----+----------+
| 1 | 11:13:00 |
+----+----------+
1 row in set (0.00 sec)
mysql> alter table example change mytime mytime datetime;
Query OK, 1 row affected, 1 warning (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 1
mysql> select * from example ;
+----+---------------------+
| id | mytime |
+----+---------------------+
| 1 | 0000-00-00 00:00:00 |
+----+---------------------+
1 row in set (0.00 sec)
So that destroys the value. I tried to go back by altering the table to time, and using a new row. Starting over:
mysql> select * from example ;
+----+----------+
| id | mytime |
+----+----------+
| 2 | 11:13:00 |
+----+----------+
1 row in set (0.00 sec)
mysql> ALTER TABLE example CHANGE mytime mytime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP();
ERROR 1067 (42000): Invalid default value for 'mytime'
mysql> ALTER TABLE example CHANGE mytime mytime DATETIME NOT NULL DEFAULT CURRENT_DATE();
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_DATE()' at line 1
Apparently, this is hard.
This is because your last_visit column is of the time and not datetime type. Initially I assumed that mysql just uses 01-01-2000 as some sort of default date for representing time fields internally, however it appears that 01-01-2000 is the doing of rails and not mysql. Look at Represent a time with no date in ruby
Run this on your mysql prompt,
ALTER TABLE visitors CHANGE last_visit last_visit datetime;
Understanding my problem using Ashish and Beck's answers, I was only storing the time in MySQL, and rails was adding on a default 2000-01-01 to it. I tried to find a way to update existing data to include the date, using today's date to update the records. The following is what I could get.
Assume we have
mysql> select * from example ;
+----+----------+
| id | mytime |
+----+----------+
| 2 | 11:13:00 |
+----+----------+
1 row in set (0.00 sec)
This how I change mytime to an updated datetime
mysql> alter TABLE example ADD new_time datetime;
Query OK, 1 row affected (0.04 sec)
mysql> UPDATE example SET new_time = CONCAT( CURDATE(), " ", mytime );
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> ALTER TABLE example DROP mytime ;
Query OK, 1 row affected (0.03 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE example CHANGE new_time mytime DATETIME;
Query OK, 1 row affected (0.04 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from example ;
+----+---------------------+
| id | mytime |
+----+---------------------+
| 2 | 2012-10-11 11:13:00 |
+----+---------------------+
1 row in set (0.00 sec)
I couldn't find a way to combine the data update and changing the field type in one example. Anyone have better ideas?