I have two different development environment which is MySQL 5.6 & Maria DB 10.0
I use WHERE query like time>="userInputBeginTime" to limit the minimum date of data.
Unfortunately, the front-side provide wrong date information(in my case, the expected input is date string formatted like "yyyy-MM-dd", but the real input was "Invalid Date" which due to javascript error)
And then i found a difference between MySQL & Maria DB
In MySQL:
SELECT NOW() > "Invalid Date" test;
+-----------+
| test |
+-----------+
| 0 |
+-----------+
In Maria DB:
SELECT NOW() > "Invalid Date" test;
+-----------+
| test |
+-----------+
| 1 |
+-----------+
This difference leads directly to the different result that MySQL returned nothing and Maria DB returned everything.
I think may be they use different methods to compare
My temporary solution is using SQL like this
SELECT * FROM table_name
WHERE
NOT ISNULL(CONVERT("userInputBeginTime",datetime))
AND time >= "userInputBeginTime"
to force Maria DB return nothing when invalid input was detected.
I would like to know if there is a better solution?
Best Regards
You can try using STR_TO_DATE to parse the string as a date in the format you expect. This function would return NULL if it cannot parse the date in the format specified. Your bad JavaScript input would fall into this category and should produce NULL:
SELECT *
FROM table_name
WHERE STR_TO_DATE(userInput, '%Y-%m-%d') IS NOT NULL AND
<other conditions here>
STR_TO_DATE in MariaDB
STR_TO_DATE in MySQL
Related
I have an old PHP system, using MySQL 5.5.47 as DB.
The guys who have created the system, have taken a strange decision.
In some cases, they saved a date value without day - for example '2018-01-00'. The field type is DATE.
A lot of queries use where clause like this: UNIX_TIMESTAMP(DATE(<DATE>)) BETWEEN 1514757600 AND 1546207210, where <DATE> is a column which contains records like '2018-01-00', '2018-02-00', etc.
The two timestamps represent dates 2018-01-01 and 2018-12-31.
On production, this type of queries run without issue.
On my local machine, they do not return any results.
What I found is if I run the command: SELECT UNIX_TIMESTAMP( DATE( '2018-01-00' ) ) on production the result is 1514757600, but on my local machine it returns 0.
I'm using a Docker compose to reproduce the production as close as possible. Initially, I have used MySQL 5.6 for local development when I hit this issue, I tried with MySQL 5.5.62, but the result is same.
Does anyone know how I can set up my local MySQL to work as the production one?
Query on production:
mysql> SELECT DATE('2018-01-00'), UNIX_TIMESTAMP(DATE('2018-01-00')), UNIX_TIMESTAMP('2018-01-00');
+--------------------+------------------------------------+------------------------------+
| DATE('2018-01-00') | UNIX_TIMESTAMP(DATE('2018-01-00')) | UNIX_TIMESTAMP('2018-01-00') |
+--------------------+------------------------------------+------------------------------+
| 2018-01-00 | 1514757600 | 0 |
+--------------------+------------------------------------+------------------------------+
Query on local:
mysql> SELECT DATE('2018-01-00'), UNIX_TIMESTAMP(DATE('2018-01-00')), UNIX_TIMESTAMP('2018-01-00');
+--------------------+------------------------------------+------------------------------+
| DATE('2018-01-00') | UNIX_TIMESTAMP(DATE('2018-01-00')) | UNIX_TIMESTAMP('2018-01-00') |
+--------------------+------------------------------------+------------------------------+
| 2018-01-00 | 0 | 0 |
+--------------------+------------------------------------+------------------------------+
It turns out to be a bug in Mysql prior 5.5.48. In the release notes of 5.5.48, there is a statement about fixing a bug related to the unix_timestamp function.
https://dev.mysql.com/doc/relnotes/mysql/5.5/en/news-5-5-48.html
When an invalid date was supplied to the UNIX_TIMESTAMP() function using the STR_TO_DATE() function, no check was performed before converting it to a timestamp value. (Bug #21564557)
The actor table in the salika sample schema defines column last_update as a timestamp. I want to render that column using JSON_ARRAY in ISO8601 format. - First shouldn't that be the default rendering for JSON_ARRAY.
From reading the documentation and comments on this website and others it appears that the answer is to use FROM_UNXTIME with an output mask that generates ISO8601 Format.
Unfortunately FROM_UNIXTIME() appears to always return NULL on my database
mysql> select current_timestamp();
+---------------------+
| current_timestamp() |
+---------------------+
| 2018-10-03 17:15:03 |
+---------------------+
1 row in set (0.00 sec)
mysql> select from_unixTime(current_timestamp())
-> ;
+------------------------------------+
| from_unixTime(current_timestamp()) |
+------------------------------------+
| NULL |
+------------------------------------+
1 row in set (0.00 sec)
mysql>
I suspect this may be caused by the fact that I have not installed the timezone configuration files.. However when I try that I get...
mysql -u root -p****** sys <timezone_posix.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1146 (42S02) at line 1: Table 'sys.time_zone' doesn't exist
Sure I've missed something obvious here....
Just try this:
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(CURRENT_TIMESTAMP()));
As mysql doc says, function FROM_UNIXTIME(unix_timestamp[,format]) only accept parameter as a UNIX_TIMESTAMP, but not a TIMESTAMP.
Luckily, there's a function UNIX_TIMESTAMP(date) transforming various types such as DATE, TIMESTAMP and so on into UNIX_TIMESTAMP. So call UNIX_TIMESTAMP(date) first, and then `FROM_UNIXTIME(
This worked for me in the end...
select json_array("actor_id","first_name","last_name",DATE_FORMAT(convert_tz("last_update", ##session.time_zone, '+00:00'),'%Y-%m-%dT%T%fZ')) "json" from "sakila"."actor"
/
which gives
[
1,
"PENELOPE",
"GUINESS",
"2006-02-15T12:34:33000000Z"
],
[
2,
"NICK",
"WAHLBERG",
"2006-02-15T12:34:33000000Z"
]
I have a table with following columns and sample data
File Name | Status
'xxx_2015-07-20.csv' | Completed
'xxx_2015-07-19.csv' | Completed
'xxx_2015-07-18.csv' | Failed
.
.
'xxx_2015-06-01.csv' | Failed
Now I have two scenarios in my application (PHP-MySQL):
1) I have to fetch the status of today's file. I can do it like this:
select status from myTable where file_name like '%date(Y-m-d)%';
2) I want to fetch the status of all files generated since 1 month from today. Suppose today is 2015-07-20, then files from 2015-06-20 should show up.
Since there is no date column, I can't apply comparison operator and get the results. I believe it will need some playing with regular expressions.
I am not familiar with regular expressions, so any help on this would be much appreciated.
If the pattern is same i.e. xxx_2015-07-20.csv you can use substring_index function to get the date value as
mysql> select substring_index(substring_index('xxx_2015-07-20.csv','_',-1),'.',1) as d;
+------------+
| d |
+------------+
| 2015-07-20 |
+------------+
Now using the same you can have the select statement as
select status from myTable
where
substring_index(
substring_index(file_name,'_',-1),
'.',1
) = curdate();
I need to treat a date field in mySQL as if it is a string. For the purposes of using the date in a LIKE statement:
select * from table where dob like some_string;
Doing this currently produces the following warning:
mysql> show warnings;
+---------+------+--------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------+
| Warning | 1292 | Incorrect date value: '1492' for column 'dob' at row 1 |
+---------+------+--------------------------------------------------------+
1 row in set (0.00 sec)
I would use DATE_FORMAT to get a string representation of your DATE column:
SELECT
*
FROM
yourtable
WHERE
DATE_FORMAT(dob, '%Y-%m-%d') LIKE '1492%';
and use the pattern that suits your need best. You find the specifiers right in the linked manual page.
Note:
MySQL can't use an index for this kind of query, so it will be slow.
Use a cast
Select *
From Table
Where Cast(dob as nvarchar(20)) Like some_string;
using the date in a LIKE statement
No. Things that this approach does wrong:
Wastes CPU time converting dates to strings.
Wastes time doing string comparisons when integer comparisons could be done.
Throws away any index on dob that might otherwise make the query more efficient.
A better approach would be something like:
SELECT *
FROM table
WHERE dob BETWEEN '1492-01-01' AND '1492-12-31'
You will always want to do as few type conversions as possible and keep the table data as-is so that indexes are properly utilized.
date = Date.today
query = "insert into custom_reports(name,description,created_at) values(#{report_name}, #{report_content}, #{date})"
ActiveRecord::Base.connection.execute(query);
it inserts
0000-00-00 00:00:00
So thought of going the mysql timestamp way. Is it possible to do?
This should work
query = "insert into custom_reports(name,description,created_at) values('#{report_name}', '#{report_content}', '#{Time.now}')"
Try, changing
date = Date.today
to
date = Time.now
Apart from the above I tend to not use variables that may or may not accidentally be a keyword (especially when I am not sure), so instead of naming variable as date, I would use d
Why do you write that SQL manually? Thats is more complicated and insecure, because you do not escape the strings in the query. On the other side ActiveRecord will take care of the created_at column.
I would prefer to have a basic model for that:
class CustomReport < ActiveRecord::Base
end
CustomRepor.create!(name: report_name, description: report_content)
Mysql "Date" type columns should use
Date.now
Mysql "Time" type columns should use
Time.now
Mysql "DateTime" type columns have to use
DateTime.now
I had to find out what is the data format on my created_at field
rails db
select created_at from users;
+---------------------+
| created_at |
+---------------------+
| 2017-12-12 00:51:19 |
| 2017-12-12 00:51:20 |
| 2017-12-12 00:51:22 |
| 2017-12-12 00:51:23 |
+---------------------+
Then I have to run the raw query according to the format I'm using.
date = Time.now.strftime("%Y-%m-%d %H:%M:%S")
query = "insert into custom_reports(name,description,created_at) values(#{report_name}, #{report_content}, #{date})"
ActiveRecord::Base.connection.execute(query);
Try Changing the timestamp to date time format:
Time.at(1335437221)
convert
2012-04-26 12:47:01 +0200