How to query oracle dates properly? - sql

select * from mytable where datecolumn == to_date('01-DEC-13','DD-MMM-YY')
I am getting the "ORA-01821: date format not recognized"
Where I do a query for a select * from mytable, I see that the values in datecolumn show up like "01-DEC-13" What am I doing wrong?

I'd recommend using the full century for dates. I've dealt with plenty of databases where somebody messed up the centuries because they didn't understand Oracle or the front-end language. Consider this for your 01-DEC-13 date:
CREATE TABLE LousyDates (DateVal DATE);
INSERT INTO LousyDates VALUES (DATE '2013-12-01');
INSERT INTO LousyDates VALUES (DATE '1713-12-01');
INSERT INTO LousyDates VALUES (TO_DATE('12/1/13 BC', 'MM/DD/YYYY BC'));
SELECT
TO_CHAR(DateVal, 'DD-MON-YY') AS NoCentury,
TO_CHAR(DateVal, 'MM/DD/YYYY BC') AS WithCentury
FROM LousyDates;
NOCENTURY WITHCENTURY
------------------ -------------
01-DEC-13 12/01/2013 AD
01-DEC-13 12/01/1713 AD
01-DEC-13 12/01/0013 BC
OK, maybe I'm overstating the point with the 13 BC date, but you get the idea :)
To use the century...
SELECT * FROM MyTable WHERE datecolumn = TO_DATE('01-DEC-2013', 'DD-MON-YYYY')
or
SELECT * FROM MyTable WHERE datecolumn = DATE '2013-12-01'

Unless you're 100% sure you will never ever use different language settings, I'd recommend using MM instead of MON:
select * from mytable where datecolumn = to_date('2013-12-01', 'YYYY-MM-DD')
This will work with any NLS settings, whereas comparing the output of to_date(...MON...) with 'DEC' will fail utterly on different locales.

Try this:
SELECT * from MYTABLE WHERE TO_CHAR(datecolumn,'DD-MON-YY') == '01-DEC-13'
instead of converting your wildcard, try to convert your datetime.

Related

Oracle use LIKE '%' on DATE

My table myTab has the column startDate, which has the datatype "DATE". The data in this column are stored like dd.mm.yyyy.
Now I'm trying to get data with this query:
SELECT * FROM myTab WHERE startDate like '%01.2015"
Somehow it doesn't work and I don't know why.
Hope someone can help.
To make a text search on the date you would have to convert the date to text.
It's more efficient if you calculate the first and last date for what you want to find and get everything between them. That way it's done as numeric comparisons instead of a text pattern match, and it can make use of an index if there is one:
SELECT * FROM myTab WHERE startDate >= DATE '2015-01-01' AND startDate < DATE '2015-02-01'
SELECT * FROM myTab WHERE TO_CHAR(startDate,'dd.mm.yyyy') LIKE '%01.2015'
If the field type is "DATE" then the value isn't stored as a string, it's a number managed by Oracle, so you have to convert it to a string:
SELECT * FROM myTab WHERE to_char(startDate, 'MM.YYYY') = '01.2015';
You can also use date ranges in SQL queries:
SELECT * FROM myTab
WHERE startDate
BETWEEN to_date('01.01.2015', 'DD.MM.YYYY')
AND to_date('31.01.2015', 'DD.MM.YYYY');
Regarding you actual question "Somehow it doesn't work and I don't know why."
Oracle make an implicit conversion from DATE to VARHCAR2, however it uses the default NLS_DATE_FORMAT which is probably different to what you use in your query.
The data in this column are stored like dd.mm.yyyy.
Oracle does not store date in the format you see. It stores it internally in proprietary format in 7 bytes with each byte storing different components of the datetime value.
WHERE startDate like '%01.2015"
You are comparing a DATE with a STRING, which is pointless.
From performance point of view, you should use a date range condition so that if there is any regular INDEX on the date column, it would be used.
SELECT * FROM table_name WHERE date_column BETWEEN DATE '2015-01-01' AND DATE '2015-02-01'
To understand why a Date range condition is better in terms of performance, have a look at my answer here.
I solved my problem that way. Thank you for suggestions for improvements. Example in C#.
string dd, mm, aa, trc, data;
dd = nData.Text.Substring(0, 2);
mm = nData.Text.Substring(3, 2);
aa = nData.Text.Substring(6, 4);
trc = "-";
data = aa + trc + mm + trc + dd;
"Select * From bdPedidos Where Data Like '%" + data + "%'";
To provide a more detailed answer and address this https://stackoverflow.com/a/42429550/1267661 answer's issue.
In Oracle a column of type "date" is not a number nor a string, it's a "datetime" value with year, month, day, hour, minute and seconds.
The default time is always midnight "00:00:00"
The query:
Select * From bdPedidos Where Data Like '%" + data + "%'"
won't work in all circumstances because a date column is not a string, using "like" forces Oracle to do a conversion from date value to string value.
The string value may be year-month-day-time or month-day-year-time or day-month-year-time, that all depends how a particular Oracle instance has set the parameter NLS_DATE_FORMAT to show dates as strings.
The right way to cover all the possible times in a day is:
Select *
From bdPedidos
Where Data between to_date('" + data + " 00:00:00','yyyy-mm-dd hh24:mi:ss')
and to_date('" + data + " 23:59:59','yyyy-mm-dd hh24:mi:ss')
SELECT * FROM myTab WHERE startDate like '%-%-2015';
This will search for all dates in 2015. If this doesn't work, try:
SELECT * FROM myTab WHERE startDate like '%-%-15';

Between & In operators- How can i give multiple conditions for a column in SQL

If i want to find # of suppliers who supplied products in 2010, 2011, 2012, 2013, all four years. how do i frame a query for that?
Between and In operators does not work.
Without knowing information about your table, if the year is stored in a column then you can do something like this
SELECT * FROM Table WHERE (year = '2010') OR (year = '2011') OR (year = '2012') OR (year = '2013');
if it's a type of DATETIME you can probably do
SELECT * FROM Table WHERE DATETIMEcolumn BETWEEN 'YYYY-MM-DD HH:MM:SS' AND 'YYYY-MM-DD HH:MM:SS'
being 'YYYY-MM-DD HH:MM:SS' the default DATETIME format of MySQL, we don't know what you are using but you get the idea.
Change the Date into Char and you can use IN:
SELECT COUNT(SUPPLIERS) FROM
(SELECT SUPPLIERS,Count(DISTINCT TO_CHAR(DATETIME_FIELD,'YYYY')) FROM TABLE_NAME
WHERE TO_CHAR(DATETIME_FIELD,'YYYY')
IN
('2010','2011','2012','2013')
GROUP BY SUPPLIERS
HAVING Count(DISTINCT TO_CHAR(DATETIME_FIELD,'YYYY'))=4);
There are many ways:
select * from TableName
where functionToExtractYear(DateColumn) in(2010, 2011, 2012, 2013)
select * from TableName
where functionToExtractYear(DateColumn) between 2010 and 2013
select * from TableName
where DateColumn >= '2010-01-01' and DateColumn <= '2014-01-01'
The last is preferable at least in Sql Server because it will use possible index on DateColumn.
You have not specified the engine you use so functionToExtractYear() may vary between different products. For Sql Server it is YEAR().

Bad date format Oracle SQL

I'm facing an issue with date format. I need the row with the max(date1)
I don't think that my query is incorrect :
SELECT column1,
column2,
date1
FROM table
WHERE date1 = (SELECT MAX(date1) FROM table);
When i use this query in dev environment with TOAD, i'm receiving that result :
column1;column2;date1
aaaaa;bbbbb;19/09/2014 14:13:21
But, when i ask our infrastructure to make this query in production, they returned me that result :
column1;column2;date1
ccccc;dddddd;14/09/26
The date isn't in good format... What can i do the receive the good date ? Does i have to specified the format in my query ? Or does the infra team messed up somethings while giving me the result ?
Thanks in advance for your help
date1 is a date column - it doesn't have any intrinsic format - that's up to the client and the environment to determine when printing it.
If you want to control the format, you need to do so explicitly with the to_char function:
SELECT column1,
column2,
TO_CHAR(date1, 'DD/MM/YYYY hh24:mi:ss')
FROM table
WHERE date1 = (SELECT MAX(date1) FROM table);

SQL Query taking between specific sysdate?

I am using Oracle DB 10g, I am trying to take data between 2 dates, in the database format of data is :
10/4/2013 9:04:38 AM
I try some sql queries but it gives error...
select * from test_table where test_execution_date between '9/2/2012' and '7/2/2013'
select * from test_table where test_execution_date between '9/2/2012 9:04:38 AM' and '7/2/2013 9:04:38 AM'
It gives always same error : ORA-01843: not a valid month
Try using
TO_DATE(thedatevalue,'MM/DD/YYYY')
You need to convert string to date
select * from test_table where test_execution_date between
TO_DATE('9/2/2012', 'DD/MM/YYYY') and TO_DATE('7/2/2013', 'DD/MM/YYYY')

sqlite select with condition on date

I have an sqlite table with Date of Birth. I would like to execute a query to select those records where the age is more than 30.
I have tried the following but it doesn't work:
select * from mytable where dob > '1/Jan/1980'
select * from mytable where dob > '1980-01-01'
Some thing like this could be used:
select dateofbirth from customer Where DateofBirth BETWEEN date('1004-01-01') AND date('1980-12-31');
select dateofbirth from customer where date(dateofbirth)>date('1980-12-01');
select * from customer where date(dateofbirth) < date('now','-30 years');
If you are using Sqlite V3.7.12 or greater
Dont use date(dateofbirth) just use dateofbirth. So your query would look like this:
select * from customer where dateofbirth < date('now','-30 years');
Using the magic docs at the sqlite website:
select * from mytable where dob < date('now','-30 years');
Try writing using the date format 'YYYY-MM-DD'
select * from mytable where dob > '1980-01-01'
A more programic way would be something like this:
select * from mytable where datediff(dob, now()) > 30
You'll Need to find specific syntax for sqlite.
select * from mytable where date(dob) > date('1980-01-10')
QLite3 has some cool new date functions. Per the docs site you can use date(), time(), datetime(), julianday(), unixepoch(), or strftime() depending on how your column data is formatted.
If you use strftime(), like my suggestion below, then you have to make sure that your column data is formatted the same way as your strftime string.
You would probably want something like:
SELECT * FROM mytable WHERE dob < strftime("%m/%d/%Y", 'now', '-30 year');
Note that you might have to change the format string here to match your own.
And here's some code that I use personally to give you a better idea of how powerful it is. It lets me get all the orders from the previous 3 months, not including this month.
SELECT * FROM orders WHERE SHIPPEDDATE > strftime('%m/%d/%Y', 'now', 'start of month', '-3 month');
The modifiers are very powerful with sqlite. The first string inside strftime() is the format, the 2nd string is when you want the date to start. 'Start of month' puts the day to 1, and '-3 month' goes back 3 months. So if I ran that today (08/03/2022), the date it uses would be 05/01/2022.