I need to write the common queries for MySQL and Oracle databases. Problem occurs when I have to put date conditions.
For example: there is one field Txn_date which is in format of '20150116' in MySQL and '16-JAN-2015' in Oracle.
I use date_format(now(),'%Y%m%d') for MySQL and to_char(sysdate,'dd-MON-YYYY') for Oracle.
Is there any common function of way by which I can use the same function in both Oracle and MySQL?
I tried Txn_date in ( date_format(now(),'%Y%m%d') OR to_char(sysdate,'dd-MON-YYYY') ) but did not work because to_char() not recognized in MySQL.
First, in MySQL dates usually have the following format when converted implicitly - 2015-01-16 - rather than 20150116. I think you can do the following in both MySQL and Oracle (it is standard SQL) - I've checked it in Oracle (10g) and it works, and it seems to work in my fiddling with MySQL:
SELECT * FROM mytable
WHERE mydate IN ( DATE '2015-01-16', DATE '2015-01-18' );
The string literal to be converted to DATE has to be of the form yyyy-mm-dd. Now this will work if your dates are dates and don't have a time portion. Now if your dates do have a time portion, then things become more difficult since MySQL uses the DATE() function to get the date portion, while Oracle would use TRUNC(). But you can get around that with judicious use of >= and <, e.g.:
SELECT * FROM mytable
WHERE ( mydate >= DATE '2015-01-16' AND mydate < DATE '2015-01-17' )
OR ( mydate >= DATE '2015-01-18' AND mydate < DATE '2015-01-19' );
Now if you want to use SYSDATE, the best thing to do would be to use the ANSI standard CURRENT_DATE or CURRENT_TIMESTAMP. These can be compared directly with no need for formatting and should work in both MySQL and Oracle. You can also do date arithmetic using INTERVAL, in which case you could try the following:
SELECT * FROM mytable
WHERE mydate > CURRENT_DATE - INTERVAL '1' DAY;
UPDATE I've been doing some thinking about this. The query immediately above doesn't really work if you want to get all the rows that have been entered today. The difficulty is that Oracle recognizes ANSI date literals as dates (that is, with no time portion), but there isn't, as far as I know, an ANSI-standard way of converting a date/time value (which an Oracle DATE is) to a date. That said, both Oracle and MySQL support the EXTRACT() function, so you should be able to do the following to get today's records:
SELECT * FROM mytable
WHERE EXTRACT(YEAR FROM mydate) = EXTRACT(YEAR FROM CURRENT_DATE)
AND EXTRACT(MONTH FROM mydate) = EXTRACT(MONTH FROM CURRENT_DATE)
AND EXTRACT(DAY FROM mydate) = EXTRACT(DAY FROM CURRENT_DATE);
Definitely unwieldy, especially if one has more than one date to consider (which I assume you do since you're using the IN operator), but should work on both platforms. See SQL Fiddle Demo here (MySQL) and here (Oracle).
MySQL and Oracle use different syntax for converting dates to strings - you'll have to use different queries.
Related
Does the following have predictable behavior, or is this not defined and up to how the database implements it?
select date '2015-01-02' > 2015;
-- or --
select '2015-01-02' > 2015;
In other words, comparing a date (or string that can be cast to a date) to an integer that is a year.
The two are quite different, because the first compares a date to a number and the second compares a string to a number.
In standard SQL, both would return an error, but the errors would be slightly different. In the first, the error would be something like "date cannot be converted to int". In the second, it would be something like "string cannot be converted to int". Most databases follow the type conversion rules of the standard.
MySQL does very strange things. It will convert a date to a number format of the form YYYYMMDD. So the first expression returns false and the second true:
select date '2015-01-01' = 2015, date '2015-01-01' = 20150101
See here.
I would strongly discourage you from depending on this behavior.
In the realm of strings, this returns true:
select '2015-01-01' = 2015
However, what looks like a similar example returns false:
select '2015.01.01' = 2015
This is because MySQL converts leading characters to a number, until it no longer can.
I would advise you to avoid even thinking about such constructs and not depending on the results of implicit conversion (explicit conversion is a different matter). The following are the best way to determine if a date falls in a particular year:
where year(date) = 2015
where date >= '2015-01-01' and date < '2016-01-01'
It is generally completely up to the database. However, here is a correct way to express your inequalities:
select date '2015-01-02' >= date '2015-01-01' AND
date '2015-01-02' < date '2016-01-01'
The above inequality checks if the '2015-01-02' date occur anywhere in the 2015 calendar year. It is also ANSI compliant, and should work on most SQL databases (though note that not all SQL databases require/use the date keyword when defining date literals).
The only databases (I know of) that would accept as valid expressions like:
date '2015-01-02' > 2015
and
'2015-01-02' > 2015
are MySql and MariaDB because they do implicit Type Conversion in Expression Evaluation.
See the demo.
SQLite would also accept the 2nd expression for the same reason, but not the 1st query because it does not use the keyword date to cast a string to date.
Databases like SQL Server, Oracle or Postgresql need explicit data type conversions (if possible) so that the 2 operands can be compared.
I have the following SQL query which works fine in MySQL:
SELECT floor(datediff(users.created_at, curdate()) / 7) AS weeks_ago,
I'm want to convert this from MySQL to PostgreSQL. How can I get this query working?
Something like this:
SELECT TRUNC(DATE_PART('day', CURRENT_DATE - users.created_at )/7) AS weeks_ago
If we subtract two DATE or TIMESTAMP in PostgreSQL, we get an interval "ddd days hh:mi:ss"
We can use DATE_PART to extract just the ddd value. (Note that the first argument 'day' is a string enclosed in single quotes, not a keyword.)
Since the MySQL expression appears to be counting weeks as intervals of 7 days, we can do the same thing in PostgreSQL, divide by 7 and take the integer portion.
(n.b. not tested)
Reference:
https://www.postgresql.org/docs/8.0/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT
I have a column where a date store in ddmmyy format (e.g. 151216). How can I convert it to yyyy-mm-dd format (e.g 2016-12-15) for calculating a date difference from the current date? I try using DATE_FORMAT function but its not appropriate for this.
If you want to get the date difference, you can use to_days() after converting the string to a date using str_to_date():
select to_days(curdate()) - to_days(str_to_date(col, '%d%m%y'))
or datediff():
select datediff(curdate(), str_to_date(col, '%d%m%y'))
or timestampdiff():
select timestampdiff(day, str_to_date(col, '%d%m%y'), curdate())
You can use the function, STR_TO_DATE() for this.
STR_TO_DATE('151216', '%d%m%y')
A query would look something like:
select
foo.bar
from
foo
where
STR_TO_DATE(foo.baz, '%d%m%y') < CURDATE()
Note: Since both STR_TO_DATE() and CURDATE() return date objects, there's no reason to change the actual display format of the date. For this function, we just need to format it. If you wanted to display it in your query, you could use something like
DATE_FORMAT(STR_TO_DATE(foo.baz, '%d%m%y'), '%Y-%m-%d')
To get the difference, we can simply subtract time
select
to_days(CURDATE() - STR_TO_DATE(foo.baz, '%d%m%y')) as diff
from
foo
If you wanted to only select rows that have a difference of a specified amount, you can put the whole to_days(...) bit in your where clause.
SELECT STR_TO_DATE('151216', '%d%m%y') FROM `table`
use this '%d%m%y'
I have a column that stores dates as text, I need to select all the entries with date less than the date of today.
If I use this:
SELECT *
FROM mytab
WHERE expire < CURRENT_DATE( )
ORDER BY expire DESC
It doesn't select the correct entries but only the ones with da_expire empty.
How can I fix it?
In the first place, why are you storing it as string?
You need to convert it to date using MySQL's builtin function so you can be able to compare it with today's date.
WHERE STR_TO_DATE(expire, '%Y/%m/%d %H:%i') < CURDATE()
This will be a little slower since it will not use any index if you have one defined on the column.
MySQL Docs: STR_TO_DATE()
Use STR_TO_DATE(expire, '%m/%d/%Y') instead of expire in the query. I have assumed you are storing the date in month day year format. You will need to adjust the format as per the string format. However, for performance reasons convert the type of expire during load/insert process .
we have a store procedure, the IN parameter is DATE today. in this procedure, a aql is to compare this today value with a table which has a timestamp column.
for example:
column A
2012-12-01 00:00:00
SQL:
select * from t where A = today.
We run this procedure in phpmyadmin, it run OK. but it's not work in command line.
Why?
Guess you may need to format both dates into a common format.. To be safe you may even add Date() or str_to_Date if required...if you are not sure column A contains a proper date...
Try this please:
SELECT * FROM tablename
WHERE DATE_FORMAT(A, '%d/%m/%Y') = DATE_FORMAT(TODAY, '%d/%m/%Y');
if you meant CURDATE() by today then try this as well,
SELECT * FROM tablename
WHERE DATE_FORMAT(A, '%d/%m/%Y') = DATE_FORMAT(CURDATE(), '%d/%m/%Y');
It's possible that the dates are in different formats and that's causing them to be not equal. You can use datediff(date1, date2) = 0 to fix this.
http://www.w3schools.com/sql/func_datediff_mysql.asp