MySQL STR_TO_DATE NULL on error - mysql

I'm currently migrating a table with dates in VARCHAR columns to a new table with DATE columns. I managed to sanitize the string values in the old table to the format "YYYY-MM-DD" but when I try to perform the insert I got an error with the date "2006-04-31" because that April only had 30 days (was a typo when it was registered),
My question is: how can I set to NULL the column when the date is invalid without getting an error? My SQL is the following:
INSERT INTO newFancyTable (created_at)
SELECT str_to_date(created, '%Y-%m-%d') FROM oldCrappyTable;
And the error is the following:
Error Code: 1292. Incorrect date value: '2006-04-31' for column 'created_at' at row 1
Thanks
UPDATE
I also tried using the following approach:
INSERT INTO newFancyTable (created_at)
SELECT CAST(created AS DATE) FROM oldCrappyTable;
With the same error, and trying to update the oldCrappyTable would return the same:
UPDATE oldCrappyTable SET created = CAST(created AS DATE);
Both return:
Error Code: 1292. Incorrect datetime value: '2006-04-31'
UPDATE 2
At last, I used multiple CASEs to isolate that invalid dates, in sum they were only 5 of them,
Nevertheless, the issue can be reproduced by doing:
CREATE TABLE dates_temp (
test_date DATE DEFAULT NULL
) ENGINE=MEMORY;
INSERT INTO dates_temp
SELECT STR_TO_DATE("2006-04-31", '%Y-%m-%d');
DROP TABLE dates_temp;

A possible workaround is to turn off strict mode, either for the whole server, for a particular session, or for just a few statements. For example:
set #old_sql_mode = ##sql_mode;
set sql_mode = '';
-- Run some statements which may result in error
set sql_mode = #old_sql_mode;
Additional Info
MySQL Documentation

In addition to #EduardoDennis answer use NULLIF to filter out zero dates:
INSERT INTO newFancyTable (created_at)
SELECT nullif(str_to_date(created, '%Y-%m-%d'), from_days(0)) FROM oldCrappyTable;
See my full answer here.

Related

How to change the format date from 'YYYY/MM/DD" to "DD/MM/YYYY" in SQL

I code in the SQL, but I want to change the date format from default of My SQL to different format "DD/MM/YYYY" to use this format to code, but I recieved an error.
More about version of SQL:
SQL: My SQL Workbench 8.0.30 build 2054668
Window 11 Pro
Language: English
So, how can I change the date format or what is the true type of "dmy"? Please help me.
This is code that I used:
set dateformat dmy
And error is:
"Error Code: 1064. 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 'dmy' at line 1"
At the moment, we don't really know the reason why you want to change the date format, but I have a couple of assumption:
You want to insert date data from front end into the table but couldn't do so due to the mismatched date format.
You want the end output to show the date format of DD/MM/YYYY instead.
Although, it may look like you need to change the table column date format, there's a way to avoid that operation entirely. However, since you've mentioned changing from YYYY/MM/DD in your title, I'm not sure if your date column is actually DATE datatype because the default MySQL should be YYYY-MM-DD. Nonetheless, I'll address the matter in this answer altogether.
Modify the date format in query and leave the table date column datatype as it is:
From DD\MM\YYYY to MySQL DATE datatype format YYYY-MM-DD
... STR_TO_DATE(data, '%d/%m/%Y')
.. from YYYY-MM-DD to DD/MM/YYYY
... DATE_FORMAT(data, '%d/%m/%Y')
You can use any of that anywhere in a query; whether in SELECT or WHERE.
If "in query" is not what you want and you still want to update the table:
Well, you have two options here:
Directly modify the column datatype then update the value:
ALTER TABLE mytable MODIFY COLUMN date_col VARCHAR(255);
UPDATE mytable SET date_col =DATE_FORMAT(date_col , '%d/%m/%Y');
Or you can add another column, populate the desired date format there and keep the original date column as it is:
ALTER TABLE mytable ADD COLUMN my_date VARCHAR(255);
UPDATE mytable SET my_date =DATE_FORMAT(date_col , '%d/%m/%Y');
this way you have the option to directly use MySQL date functions on the default MySQL date column without the hassle of converting your desired date format into the default before you can use date functions. What I'm saying is something like this:
DAY(mysql_default_dateformat)
is similar to
DAY(STR_TO_DATE(your_dateformat, '%d/%m/%Y'))
which means that you can use DAY() (date function) on the default date format directly without the need to convert what is not default first.
Here's demo fiddle examples

Inserting date from working subselect occurs in error

Context:
CREATE TABLE dates (
date DATE
);
I have following select query which returns 2000-01-01, because LAST_DAY function returns null because of invalid date.
Edit: I know that 2012-02-31 is incorrect date. That's the point of this question.
SELECT IFNULL(LAST_DAY('2012-02-31'), '2000-01-01'); // returns 2000-01-01
However when I try to insert this result into the table it returns an error:
Query Error: Error: ER_TRUNCATED_WRONG_VALUE: Incorrect datetime value: '2012-02-31'
INSERT INTO dates (date)
SELECT IFNULL(LAST_DAY('2012-02-31'), '2000-01-01');
Why does it happen like that? What's the explanation?
DB Fiddle

How to update empty time in datetime MySQL

We are storing datetime in a column on our MySQL database, formatted in TEXT, but when our datetime is supposed to look like below:
'xxxx-xx-xx 00:00:00'
The time is deleted or not show on our datetime, and therefore our datetime, at that specific time, only contains the date:
'xxxx-xx-xx'
What we want is first of all to figure out why this is occurring, but for now we need to edit every row, and make sure the datetime is also showing the time. We have tried to change the impacted rows by using this query:
UPDATE table SET TIME(col_datetime) = '00:00:00' WHERE LENGTH(TIME(col_datetime)) = 0;
Above query should update the time on the datetime for col_datetime, where length of time is 0. Unfortunately, we receive an error, and we can't run the query. This is the error:
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 '(time_start) = '00:00:00' WHERE LENGTH(TIME(time_start)) = 0' at line 2
How can we change time on our datetime, where time is not shown?
Don't store dates as strings. Instead, you want to use the datetime datatype: it has a time part, that defaults to 00:00:00 when not specified.
Here is a small conversion script for that purpose:
alter table mytable add col_datetime_new datetime;
update mytable set col_datetime_new = col_datetime;
alter table mytable drop col_datetime;
alter table mytable change column col_datetime_new col_datetime datetime;
This leverages the fact that you are using format YYYY-MM-DD in your string dates, so conversion to datetime is seemless.

How to change column type from text to date in mysql

I uploaded a csv file to a mysql database. Inside the table there is a time column, which has as the name already says time information :), please have a look
This column is saved as text
I try to convert time column in datetime, and found following help on stackoverflow MySQL alter table and convert data from text to datetime
So I tried to go the same way, i.e.
alter table 'tablename' add column new_column_name date;
update 'tablename'
set new_column_name=str_to_date(column_with_time_saved_as_text,'YYYY-MM-DD hh:mm:ss')
If I execute the script I get following error
Error Code: 1411. Incorrect datetime value: '2019-07-03 23:47:46.254+02' for function str_to_date
I suppose there is an issue with the timezone.I tried to find out a solution but I could not. Thanks for any kind of advice
This error:
Error Code: 1411. Incorrect datetime value: '2019-07-03
23:47:46.254+02' for function str_to_date
means that you are using a wrong formatting parameter, as explained here you must use formatters in the form %dateField like this:
SELECT STR_TO_DATE("August 10 2017", "%M %d %Y");
Alternatively, you can use SUBSTRING to get only the datetime part you need:
alter table 'tablename' add column new_column_name datetime;
update 'tablename' set new_column_name = SUBSTRING(column_with_time_saved_as_text, 1, 19)
You can perform str_to_date
SELECT DATE_FORMAT(STR_TO_DATE('2019-11-03 23:59:46.254+02', '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s') dt;
dt
2019-11-03 23:59:46
Using '%Y-%m-%d %H:%i:%s' update the table
alter table 'tablename' add column new_column_name datetime;
update 'tablename'
set new_column_name= DATE_FORMAT(STR_TO_DATE(column_with_time_saved_as_text,19), '%Y-%m-%d %H:%i:%s'), '%Y-%m-%d %H:%i:%s');
But this will ignore the '254+02'.

How to convert date and update a joined table

I am trying to update a column in table, based on data (that is constantly updated) in a temporary table (via csv imports). The date in the temporary table is VARCHAR ("2/20/2014 10:29:25 AM" format) and the date in the table I want to update is in DATETIME type.
I'm not sure how to properly join these two tables to update the dates in the permanent table based on the current date showing in the temp table...using product_sku (in both tables) as the joining field.
Here is what I have tried, but keep getting SQL error (' #1064 - 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 'FROM...)
Update t0
set t0.product_available_date =
(SELECT STR_TO_DATE( `t1.product_available_date`,
'%c/%e/%Y %H:%i' ))
FROM cpg5443_virtuemart_products as t0
join cpg5443_virtuemart_products_temp as t1
on t0.product_sku = t1.product_sku
Where t0.product_sku='002-765-AS'
Do you see any glaring mistakes and can you advise how I can correct? In the end, I will want the where statement to say "where t0.product_sku=t1.product_sku" with hopes this will update this column for every record based on the date in the temp table. For now, I'm just testing the update with one product_sku.
Looks like you are missing parentheses after '002-765-AS'. Have you posted all the code? Also you have an extra parentheses after the date format.
Try this:
update cpg5443_virtuemart_products as t0
inner join cpg5443_virtuemart_products_temp t1
on t0.product_sku = t1.product_sku
set t0.product_available_date = str_to_date (t1.product_available_date,
'%c/%e/%Y %H:%i:%s')
where t0.product_sku = '002-765-AS'