Why does MySQL ignore mutiple dash delimiters in DATE columns? - mysql

Why does the below condition work? Does MySQL convert multiple dashes '---' to a single '-' dash. I tried finding an explanation for this but I couldn't find anything.
WHERE DATE(login_at) = '2019---04---30'
Can anyone explain to me how this works?
I'm using MySQL Version : 5.7.18

MySQL allows a flexibility, by auto-interpreting various delimiters, and converts them to proper date[time] format. It is well explained in documentation:
MySQL permits a “relaxed” format for values specified as strings, in
which any punctuation character may be used as the delimiter between
date parts or time parts. In some cases, this syntax can be deceiving.
For example, a value such as '10:11:12' might look like a time value
because of the :, but is interpreted as the year '2010-11-12' if used
in a date context. The value '10:45:15' is converted to '0000-00-00'
because '45' is not a valid month.
The only delimiter recognized between a date and time part and a
fractional seconds part is the decimal point.
So, in your case, MySQL is considering the delimiter as ---, and thus implicitly converting to Y-m-d format.
However, it is always better and safe to use the standard Y-m-d h:i:s format, to represent a date/datetime value.

Related

questions about the datetime type values

I have several things which I want to discuss with you guys.
Since, they were just simple questions, so no dataset here.
Suppose I have a datetime type column which called started_date, the value in it was like:
yyyy-mm-dd hh:mm:ss. So, if I want to select some IDs which were larger than one specified day (let's say June/01/2017), can I just using
select ID, started_date
from table1
where started_date>"2017-06-01";
Does this work?
I tried some samples, and it worked indeed in the mysql. However, someone told me that I cannot compare the datetime column with string values without converting their format. And it confused me. Because I thought the value "2017-06-01" here was date type value, so it does not need convert. Or am I thinking wrong?
Another thing was about the double quote and single quote, I understand that the single quote was used for string values. However, in this case, when I used double quote to quote "2017-06-01", it works. So, does it mean the double quote can quote date values?
I am just asking, so any response is welcome.
Thanks.
Your query is fine. You are using a safe date/time format for the string. In other words, if you have to store the value as a string, then use that format.
I would write the code as:
where started_date >= '2017-06-01'
I see no reason to exclude midnight on 2017-06-01 (although you might have a reason). Second, single quotes are the standard delimiter for strings.
That said, you can store the value as a string.
As a best practice, I stay away from comparing time-stamps to date-stamps. In this case you can be explicit and truncate the start date. And yes, use single quotes instead.
where SUBSTR(started_date, 1, 10) > '2017-06-01'
To make sure it works you could just convert the date time to a string first and compare the two strings:
to_char(started_date,'YYYY-MM-DD') >= '2017-06-01'
The Strings will compare just fine in that format.

Format Function returns wrong value

We have a field in a query that should be left-padded with zeroes if it is too short, and we accomplish this using the Format() function. However, there are some values that produce bizarre results.
Format("14425112-8","00000000-00")
Returns the value "00019330-78"
For most inputs, the string gets formatted as expected, 8 digits, hyphen, two digits. But in a few rare cases, the value is modified. Is this repeatable for anyone else? Does anyone have an explanation?
Thanks for your help.
This is an example of access trying to be too helpful. It looks like it is interpreting these values as dates, but since you didn't use any date indicators in the format e.g: (dd,mm,yyyy), it converted 1-1 to a date, and then tried to display it in decimal form:
debug.print Format("1-1","000000-00")
returns 000427-36 which is the decimal value 42736 which, if you convert to a date, becomes 1/1/2017. This is what access interpreted "1-1" as.
it seems that access has reserved the - character as symbolizing a date format, despite what their website says. This function is only useful for formatting actual dates, or numeric values, such as prices. If you are set on using the format function, you will have to change you separator to a decimal point, which apparently is the only character that will get you what you want with the leading and trailing zeros.
Otherwise, you may have to build your own function for this.
You cannot format a string like a number this way. Try this:
PaddedNumber = Right(String(8, "0") & "14425112-8", 10)

MySQL timestamp format and datediff

Hi I'm writing queries for MySQL, and now my database has a column containing the timestamp in this format: 7/14/2015 7:57:49 AM, but I need to use the DATEDIFF function, so how can I convert the timestamp into the format like: 2015-7-14 (or 2015-07-14, I'm not sure which one is correct; just the date)?
This should convert your string to just the date in a date format, then you can use DATEDIFF on the date fields in question:
SELECT STR_TO_DATE(LEFT(t,LOCATE(' ',t) - 1), '%m/%d/%Y') FROM my_table;
The LEFT function will take the substring to the left of the space, which is just your date, then STR_TO_DATE will convert that substring to a date the system can use.
(Not knowing your field and table names, I used t and my_table.)
You don't need to. The way MySQL displays timestamps has nothing to do with the way they're stored internally; as long as it's TYPE TIMESTAMP or some compatible type, the DATEDIFF() function will know what to do with it.
TIMESTAMPs are actually stored as a really huge integer representing (I think) milliseconds from Midnight UTC, January 1st, 1970. The display format is determined by a system global variable, and has nothing to do with the actual value.
Converting from a string to a DATETIME or TIMESTAMP is actually also fairly straightforward using the STR_TO_DATE() function; in your case the format string would be something like
STR_TO_DATE('%c/%e/%Y %l:%i:%s %p', datecol)
although you might have to experiment a bit to make it work reliably.

MySQL String to Date converting with varying strings?

I need to convert dates of varying strings. They come in 3 different ways.
yyyy/mm/dd
mm/dd/yyyy
or blank (can fill in some default)
What is a good way to handle this situation for an INSERT statement?
Use STR_TO_DATE function in combination with COALESCE - something like:
set #strdate := '2014/05/10';
select COALESCE(STR_TO_DATE(#strdate,'%m/%d/%Y'),STR_TO_DATE(#strdate,"%Y/%m/%d"))
You can use MySQL str_to_date() function. It requires one format and will return NULL if the data doesnt match the format. UseCoalesce with str_to_date with str_to_date in descending order of likelihood of the format.
Example if yyyy/mm/dd is more common than mm/dd/yyyy then use
COALESCE(STR_TO_DATE(your_date_here,'%Y/%m/%d'),STR_TO_DATE(#strdate,"%m/%d/%Y"))
Edit: This is the same as Ondřej Šotek's answer but with a possible performance improvement

MySQL and datetime

If I have a table with a DATETIME column I can insert dates that have a format like:
2015-03-25 10:10:10
2015-03-25 10:10
2015-03-25 10
2015-03-25
It will fill in the remainder with zeros. I can't however use
2015-03
2015
As it will give an 'Incorrect datetime value' error. It is however possible to use these last two in a SELECT like [..] WHERE timestamp < '2015-03' ..
Is there a way that MySQL will fill in the remainder of datetimes with 01-01 for the month and day if omitted in datetimes or do I have to do that manually myself?
I.e. I would like to use '2015-03' in an INSERT statement, or do something like SELECT DATE_FORMAT('2015-03', '%Y%m%dT%H%i%S')
As stated in Date and Time Literals:
MySQL recognizes DATE values in these formats:
As a string in either 'YYYY-MM-DD' or 'YY-MM-DD' format. A “relaxed” syntax is permitted: Any punctuation character may be used as the delimiter between date parts. For example, '2012-12-31', '2012/12/31', '2012^12^31', and '2012#12#31' are equivalent.
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'.
As a number in either YYYYMMDD or YYMMDD format, provided that the number makes sense as a date. For example, 19830905 and 830905 are interpreted as '1983-09-05'.
MySQL recognizes DATETIME and TIMESTAMP values in these formats:
As a string in either 'YYYY-MM-DD HH:MM:SS' or 'YY-MM-DD HH:MM:SS' format. A “relaxed” syntax is permitted here, too: Any punctuation character may be used as the delimiter between date parts or time parts. For example, '2012-12-31 11:30:45', '2012^12^31 11+30+45', '2012/12/31 11*30*45', and '2012#12#31 11^30^45' are equivalent.
The only delimiter recognized between a date and time part and a fractional seconds part is the decimal point.
The date and time parts can be separated by T rather than a space. For example, '2012-12-31 11:30:45' '2012-12-31T11:30:45' are equivalent.
As a string with no delimiters in either 'YYYYMMDDHHMMSS' or 'YYMMDDHHMMSS' format, provided that the string makes sense as a date. For example, '20070523091528' and '070523091528' are interpreted as '2007-05-23 09:15:28', but '071122129015' is illegal (it has a nonsensical minute part) and becomes '0000-00-00 00:00:00'.
As a number in either YYYYMMDDHHMMSS or YYMMDDHHMMSS format, provided that the number makes sense as a date. For example, 19830905132800 and 830905132800 are interpreted as '1983-09-05 13:28:00'.
Notably, MySQL does not support the incomplete formats that you wish to use.
That MySQL happens to accept some of the incomplete formats you've tried (apparently by padding with zeroes) is undocumented behaviour, quite possibly unintended by the developers. It cannot (and should not) be relied upon, not least because edge cases could exist under which the behaviour breaks; or because the behaviour could be changed without warning in a future release.
If it's absolutely necessary to provide such incomplete temporal literals to MySQL (which it shouldn't be, as your data access layer ought to be aware of the type of values it is handling and provide them to MySQL in a supported format), you can use its STR_TO_DATE() function to parse them accordingly:
Unspecified date or time parts have a value of 0, so incompletely specified values in str produce a result with some or all parts set to 0:
mysql> SELECT STR_TO_DATE('abc','abc');
-> '0000-00-00'
mysql> SELECT STR_TO_DATE('9','%m');
-> '0000-09-00'
mysql> SELECT STR_TO_DATE('9','%s');
-> '00:00:09'
Range checking on the parts of date values is as described in Section 11.3.1, “The DATE, DATETIME, and TIMESTAMP Types”. This means, for example, that “zero” dates or dates with part values of 0 are permitted unless the SQL mode is set to disallow such values.
So, for example, you might use:
STR_TO_DATE('2015-03', '%Y-%m');
Try unix_timestamp()
SELECT like [..] WHERE unix_timestamp(timestamp) < '2015-03'