Oracle date format problem - oracle

I have the following strange problem in Oracle
(Please keep in mind that I have little experience in SQL and even less in Oracle).
If I do this:
SELECT TO_CHAR(sysdate, 'YYYY-MM-DD HH24:MI') FROM dual
I get this:
2010-12-02 18:39
All fine there.
However, if I do this:
UPDATE favorite_item
SET favorite_item.last_used_date = TO_DATE(sysdate, 'YYYY-MM-DD HH24:MI')
WHERE favorite_item.favorite_item_id = 1
I get this in my database:
10-DEC-02
Which is the 10th of December '02 which is not correct
If I do this to confirm:
SELECT TO_CHAR(favorite_item.last_used_date, 'YYYY-MM-DD HH24:MI') AS last_used_date
FROM favorite_item
WHERE favorite_item.favorite_item_id = 1
I get this:
0002-12-10 00:00
Which is completely wrong.
What am I doing wrong? I feel that the date setting is not working correctly.
Thanks in advance for your help.

Don't use TO_DATE() on sysdate; sysdate is already a date.
UPDATE favorite_item
SET favorite_item.last_used_date = sysdate
WHERE favorite_item.favorite_item_id = 1`

The problem is using the to_date() function on anything other than a string.
As to why you are getting the wrong results, there is an internal conversion that happens when you use to_date on a date. Since to_date actually takes input as a string, your date is initially converted into a string (according to your NLS_DATE_FORMAT setting) and then converted back to a date. Hence the mismatch.
SQL> select sysdate from dual;
SYSDATE
---------
02-DEC-10
SQL> select to_date(sysdate,'YYYY-MM-DD') from dual;
TO_DATE(S
---------
10-DEC-02
--- This is because, the above string is actually executed as
SQL> select to_date(
to_char('02-DEC-10','YYYY-MM-DD') from dual;
TO_DATE('
---------
10-DEC-02
SQL> select to_date(
2 /* implicit conversion... dd-mon-yy' is my session's NLS_DATE_FORMAT */
3 to_char(sysdate,'dd-mon-yy'),
4 'YYYY-MM-DD')
5 from dual;
TO_DATE(/
---------
10-DEC-02

sysdate returns a date, so converting it to a date using to_date(sysdate, ...) is redundant/not necessary. You're getting that odd result because the date is being cast to a string by the to_date function using the Oracle default of "DD-MON-YY" and then back into a date using your supplied format, "YYYY-MM-DD". Since the formats don't match, Oracle is interpreting the year as the day and the day as the year. This works correctly (but, again, is redundant):
select to_date(sysdate, 'DD-MON-YY') from dual;

Related

How to convert DATETIME in specific format to DATE in PL/SQL

I apologize for asking a simple question, but I could not find the answer on the forum.
I need to convert from this datetime '2009-06-18T00:00:00+06:00' to format 'YYYY-MM-DD' in PL/SQL.
If this "datetime" is really a timestamp (as it looks like), not a string, then you can choose how to display it (using TO_CHAR) or convert to DATE (using TO_DATE), or simply TRUNCATE it. Note that the last two results (i.e. the way they are displayed) depend on current NLS settings (set by my ALTER SESSION).
Here's an example:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test
2 as (select to_timestamp_tz ('2009-06-18T00:00:00+06:00',
3 'yyyy-mm-dd"t"hh24:mi:ss tzh:tzm')
4 col
5 from dual)
6 select to_char (col, 'yyyy-mm-dd') res1,
7 to_date (to_char (col, 'yyyy-mm-dd'), 'yyyy-mm-dd') res2,
8 trunc (col) res3
9 from test;
RES1 RES2 RES3
---------- ---------- ----------
2009-06-18 18.06.2009 18.06.2009
SQL>
Use TO_DATE on the first 10 characters in your timestamp string:
SELECT TO_DATE(SUBSTR('2009-06-18T00:00:00+06:00', 1, 10), 'YYYY-MM-DD') FROM dual
Demo
Documentation is the best part.
http://www.sqlines.com/oracle-to-sql-server/to_date
you can use the TO_DATE(string, format) function for that so it will be like
SELECT TO_DATE('2012-06-05', 'YYYY-MM-DD') FROM xyz;
DEPENDS on the data type.
If the column is DATE data type, then, as suggested already, TRUNC would do the job to display. But, if your locale-specific NLS date settings are different, then you will still see the time portion as midnight.
Else, you need to use TO_DATE with proper FORMAT and apply TRUNC to it.
update
If you only want to display, use TO_CHAR, else, if you have a filter in your WHERE clause, then remember TO_CHAR doesn't return DATE, it converts it into literal.

Use time in between in oracle for multiple date

Select *
from mytable
where paid_time Between to_date('00:00:00','HH24:MI:SS' ) and to_date('00:59:59','HH24:MI:SS')
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
Note :
1. I need perticular time period only for 10 days
Error :
1. data is there but returning Zero kindly help to solve this
You need to use the full date and time TO_DATE otherwise there is conflicting WHERE clauses'DD/MM/RRRR hh24:mi:ss'.
SELECT *
FROM mytable
WHERE paid_time BETWEEN TO_DATE('01/08/2016 00:00:00', 'DD/MM/RRRR hh24:mi:ss') AND TO_DATE('10/08/2016 00:59:59', 'DD/MM/RRRR hh24:mi:ss');
If paid_time is a string then your query will only work at all for certain NLS_DATE_FORMAT settings, due to the implicit conversion you are forcing:
alter session set nls_date_format = 'RRRR-MM-DD';
with mytable (paid_date, paid_time) as (
select date '2016-08-02', '00:01:02' from dual
)
Select *
from mytable
where paid_time Between to_date('00:00:00','HH24:MI:SS' ) and to_date('00:59:59','HH24:MI:SS')
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
no rows selected
alter session set nls_date_format = 'YYYY-MM-DD';
-- same query
ORA-01841: (full) year must be between -4713 and +9999, and not be 0
alter session set nls_date_format = 'DD/MM/RRRR';
-- same query
ORA-01847: day of month must be between 1 and last day of month
... etc.
When you do to_date('00:00:59','HH24:MI:SS') the generated date defaults to the first of the current month, so when run today it will get a September date:
select to_char(to_date('00:00:59','HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(TO_DATE('00
-------------------
2016-09-01 00:00:59
You are then trying to compare your paid_time string with that date, which means the string is implicitly converted to a date using your NLS settings, e.g.:
alter session set nls_date_format = 'RRRR-MM-DD';
select to_char(to_date('00:01:02'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(TO_DATE('00
-------------------
2000-01-02 00:00:00
So your filter is really looking for rows where the time string, incorrectly converted to a date (exactly which date depends on your actual NLS setting, and many values will error whatever the setting), is in the first minute of the first day of the current month. Which is very unlikely to ever match anything.
If it is a string and is always formatted consistently then you can just compare as a string:
with mytable (paid_date, paid_time) as (
select date '2016-08-02', '00:01:02' from dual
)
Select *
from mytable
where paid_time Between '00:00:00' and '00:59:59'
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
PAID_DATE PAID_TIM
---------- --------
2016-08-02 00:01:02
As mentioned in comments Oracle's data datatype includes the time, so storing the date (at midnight, presumably) and the time in separate columns just adds complexity and inefficiency.

Alter a datetime in Oracle and set time to 9 am

i have 28-APR-2016 10:05:07 date as parameter in stored procedure. This may be the current time also as string date.
i need to set the time to 9 am to check the shift start timing.
SELECT TO_DATE('28-APR-2016 10:05:07', 'DD-MON-YYYY HH24:MI:SS') FROM dual;
I am new to oracle. Help is appreciated.
If you want the date with 9:00 a.m., then you can do:
SELECT TRUNC(TO_DATE('28-APR-2016 10:05:07', 'DD-MON-YYYY HH24:MI:SS')) + 9/24.0
FROM dual;
You can also use:
SELECT TRUNC(TO_DATE('28-APR-2016 10:05:07', 'DD-MON-YYYY HH24:MI:SS')) + INTERVAL '9' HOUR
FROM dual;
I'm just old-fashioned so I tend to use the first method.

using update in oracle

I have a column named date_col of data-type date. What's wrong with this query?
update test set date_col = to_date(sysdate,'DD-Mon-YYYY HH24:MI:SS')
Only date mon and yy is visible. not the time.
How can I make it work?
SYSDATE is yet a date. You don't need to cast SYSDATE to date type because it is a date_
update test
set date_col = sysdate
To see time fraction use to_char:
select to_char(date_col, 'HH24 MI')
from test;

Date function on oracle

I've got a question about date function on oracle.
I have the following table
statistic_table(
pages AS varchar(10),
date_created AS date
);
I have the following sql
SELECT COUNT(*) FROM statistic_table WHERE date_created BETWEEN sysdate-5 AND sysdate-1
and
SELECT COUNT(*) FROM statistic_table WHERE date_created BETWEEN to_date('12-AUG-2011') AND to_date('16-AUG-2011');
the question is, why is it return different numbers. assuming sysdate-5 returns 12-aug-2011 and sysdate-1 returns 16-aug-2011
Any help would be much appreciated!
Cheers,
sysdate - 5 will give you a date with the current time. So if I ran it at 1pm precisely, the query would be equivalent to:
select (*)
FROM statistic_table
WHERE date_created BETWEEN to_date('12-Aug-2011 13:00:00')
AND to_date('16-Aug-2011 13:00:00')
whereas the second query is:
select (*)
FROM statistic_table
WHERE date_created BETWEEN to_date('12-Aug-2011 00:00:00')
AND to_date('16-Aug-2011 00:00:00')
you should probably try this instead:
select (*)
FROM statistic_table
WHERE date_created BETWEEN trunc(sysdate) -5
AND trunc(sysdate) -1
A date in Oracle is a point in time with a precision of a second.
SYSDATE returns the current date and time and is therefore not the same as to_date('17-AUG-2011'):
SQL> SELECT to_char(sysdate, 'dd-mon-yyyy hh24:mi:ss') FROM DUAL;
TO_CHAR(SYSDATE,'DD-MON-YYYYHH
------------------------------
17-aug-2011 15:52:13
Use the TRUNC function if you only want the date component:
SQL> SELECT to_char(trunc(sysdate), 'dd-mon-yyyy hh24:mi:ss') FROM DUAL;
TO_CHAR(TRUNC(SYSDATE),'DD-MON
------------------------------
17-aou-2011 00:00:00
Because SYSDATE includes a time component, so if the current time is 11:22:33, then
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN sysdate-5 AND sysdate-1
is actually equivalent to
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN to_date('12-AUG-2011 11:22:33','DD-MON-YYYY HH24:MI:SS')
AND to_date('16-AUG-2011 11:22:33','DD-MON-YYYY HH24:MI:SS')
To avoid the time component do this:
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN TRUNC(sysdate)-5 AND TRUNC(sysdate)-1
An Oracle DATE always has a day and a time component.
sysdate-5 returns a date exactly 5 days ago. If today is August 17 at 10 AM, for example, sysdate-5 returns August 12 at 10 AM.
to_date('12-AUG-2011', 'DD-MON-YYYY'), on the other hand, returns August 12 at midnight. So it returns a date that is 10 hours earlier than sysdate-5.
sysdate auto returns with a time component as mentioned by the previous answers.
When using to_date it is converting a string to a date. With this being said you can pass in parameters to make it return the same thing.
Have a look at this link that explains it.
to_date parameters

Resources