Between 2 date/times in PL/SQL not giving expected answers - oracle

I have a query in PL/SQL on Oracle 10g that isn't behaving as I thought. I'm 100% sure I am doing something silly so I'm sorry.. Here goes:
I have some data in a table that looks like this:
I then went to query but using the time element, like this:
select * from dw_time
where createdtime > to_date('2012/04/12 03:06:00', 'yyyy/mm/dd hh24:mi:ss')
When this is executed we get records returned that include the rows in the image 03:05AM. So thinking it was the to_date function I checked that:
select to_date('2012/04/12 10:24:00', 'yyyy/mm/dd hh:mi:ss')
from dual;
Now I was totally confused as it clearly know that as a time. So I tried it again:
select * from dw_time
where createdtime > to_date('2012/04/12 03:06:00', 'yyyy/mm/dd hh24:mi:ss')
As you can see it is totally ignoring the time component! At this point I thought it was time to ask the gurus on here!
Many thanks
Mike

Is it possible that in your table '12/4/2012' means 4 Dec 2012 and query outputs it in MM/DD/YYYY format?

Look at DB output date format - it's MM/DD/YYYY - you can see it on output of:
select to_date('2012/04/12 10:24:00', 'yyyy/mm/dd hh:mi:ss') from dual;
So change your select to:
select * from dw_time where createdtime > to_date('2012/12/04 03:06:00', 'yyyy/mm/dd hh24:mi:ss')
You can see date output format by this query:
select * from nls_session_parameters where parameter = 'NLS_DATE_FORMAT';
And you can change date output format by this:
alter session set NLS_DATE_FORMAT='DD/MM/YYYY HH24:MI:SS';

Related

mixing and matching data types to produce a desired date format of mm/dd/yyyy

Let me start with I have a confused Oracle table that has 2 particular columns in it, 1 for issuedate VARCHAR2(10) and one for compdate VARCHAR2(8). The NLS_DATE_FORMAT for the system session is 'YYYY-MM-DD HH24:MI:SS'. I cannot change the NLS_DATE_FORMAT as there are a significant set of SELECT's that use this format to convert other timestamps into dates.
issuedate is 'MMDDYYYY' COMPDATE is 'MM/DD/YYYY'
here are the portions of the Select in question
co.issuedate issued,
to_date(substr(ae.cdts, 1,8)) DATE_JOB_OPENED,
TO_DATE(substr(ae.xdts, 1,8)) DATE_JOB_CLOSED,
co.compdate WORKED,
The goal is to subtract
issued-WORKED
and get the result in number of days.
Guidance is appreciated
The first part of the solution should be to fix your table so that you are storing date values in a DATE data type and NOT in a VARCHAR2.
The second part of the solution should be to go back through all your old code and fix any instances where you use TO_DATE or TO_CHAR to make sure they always are passed a second argument to explicitly set the format model and to never rely on an implicit format model set by the NLS_DATE_FORMAT session parameter.
Since you are storing it as a VARCHAR2, just use TO_DATE and subtract to get the difference:
SELECT co.issuedate issued,
TO_DATE(substr(ae.cdts, 1,8), 'YYYYMMDD') DATE_JOB_OPENED,
TO_DATE(substr(ae.xdts, 1,8), 'YYYYMMDD') DATE_JOB_CLOSED,
co.compdate WORKED,
TO_DATE(co.issuedate, 'MMDDYYYY') - TO_DATE(co.compdate, 'MM/DD/YYYY')
AS days_difference
FROM ...;
and get the result in mm/dd/yyyy format.
If you really want the difference in days, months and years then it gets more complicated:
SELECT issued,
DATE_JOB_OPENED,
DATE_JOB_CLOSED,
worked,
TO_CHAR(
EXTRACT(MONTH FROM (issued_date - comp_date) YEAR TO MONTH),
'FM00'
)
||'/'||
TO_CHAR(
issued_date - ADD_MONTHS(comp_date, FLOOR(MONTHS_BETWEEN(issued_date, comp_date))),
'FM00'
)
||'/'||
TO_CHAR(
EXTRACT(YEAR FROM (issued_date - comp_date) YEAR TO MONTH),
'FM0000'
) AS difference
FROM (
SELECT co.issuedate issued,
TO_DATE(substr(ae.cdts, 1,8), 'YYYYMMDD') DATE_JOB_OPENED,
TO_DATE(substr(ae.xdts, 1,8), 'YYYYMMDD') DATE_JOB_CLOSED,
co.compdate WORKED,
TO_DATE(co.issuedate, 'MMDDYYYY') AS issued_date,
TO_DATE(co.compdate, 'MM/DD/YYYY') AS comp_date
FROM table_name co
-- ...
);
Which, for the sample data:
CREATE TABLE table_name (issuedate, compdate) AS
SELECT '10292021', '01/01/2021' FROM DUAL;
Outputs for the co related columns:
ISSUED
WORKED
DIFFERENCE
10292021
01/01/2021
10/28/0000
db<>fiddle here

How do I separate the time and date in SQL navigator?

I am trying to separate the time and date in one column to be independent off each other. I am new at writing scripts
this is my query:
select
*
from
[tablename]
where
to_date([column_name]) in ( '15-Jun-2021', '16-Jun-2021' )
and
to_char([column_name],'dd-Mon-yyyy HH:MM:ss') < '15-Jun-2021 19:54:30'
The way you put it, it would be
select *
from your_table
where date_column >= date '2021-06-15'
and date_column < to_date('15.06.2021 19:54:30', 'dd.mm.yyyy hh24:mi:ss')
because
date_column should be of date datatype. If it isn't, you'll have problems of many kinds in the future. Therefore,
don't to_date it, it is already a date
don't to_char it either, because you'd be comparing strings and get unexpected result. Use that function when you want to nicely display the result
the second condition you wrote makes the first one questionable. If date_column is less than value you wrote, then you can omit date '2021-06-16' from the first condition because you won't get any rows for that date anyway
date literal (date '2021-06-15') sets time to midnight, so condition I wrote should return rows you want
SQL> select date '2021-06-15' first,
2 to_date('15.06.2021 19:54:30', 'dd.mm.yyyy hh24:mi:ss') second
3 from dual;
FIRST SECOND
------------------- -------------------
15.06.2021 00:00:00 15.06.2021 19:54:30
SQL>

encountered an invalid number error calling the below oracle stored procedure

SELECT Ticket, ETRs, "Last ETR","Last ETR Time Change","STAR Restore Time","Restore Time - Last ETR"
FROM(
SELECT e.xsystemjob Ticket,
a.eventkey Event,
(select count(generatedtime) from obvwh.ops_ertchangelog_fact where eventkey = a.eventkey) ETRs,
to_char(a.ERT, 'MM/DD/YYYY HH24:MI:SS') "Last ETR", --GENERATEDTIME,
to_char(generatedtime, 'MM/DD/YYYY HH24:MI:SS') as "Last ETR Time Change",
to_char(e.restdate,'MM/DD/YYYY HH24:MI:SS') as "STAR Restore Time",
round(((e.restdate - a.generatedtime) * 1440),0) as "Restore Time - Last ETR"
FROM obvwh.ops_ertchangelog_fact a
join obvwh.ops_event_dim e
on a.eventkey = e.eventkey
where a.generatedtime = (select max(generatedtime) from obvwh.ops_ertchangelog_fact where eventkey = a.eventkey)
)
WHERE Substr(Ticket,0,1) = region
AND to_char("Last ETR", 'MM/DD/YYYY') between to_char(start_date,'MM/DD/YYYY') and to_char(end_date,'MM/DD/YYYY');
From you inner query, Last ETR is a string, representing the column value in format MM/DD/YYYY HH24:MI:SS. You're trying to convert that string to a string, passing a single format mask, and that is throwing the error.
You can see the same thing with a simpler demo:
select to_char('07/18/2016 12:13:14', 'MM/DD/YYYY') from dual;
Error report -
SQL Error: ORA-01722: invalid number
You could explicitly convert the string to a date and back again:
select to_char(to_date('07/18/2016 12:13:14', 'MM/DD/YYYY HH24:MI:SS'), 'MM/DD/YYYY') from dual;
TO_CHAR(TO
----------
07/18/2016
... but in the context of your comparison that doesn't really make sense anyway if the range you're comparing with can span a year end - the format mask you're using doesn't allow for simple comparison. Assuming start_date and end_date are dates (with their times set to midnight) you could do:
AND to_date("Last ETR", 'MM/DD/YYYY HH24:MI:SS') between start_date and end_date;
or even simpler, use the original raw ERT value (which is presumably already a date), and convert it to a string - if that is actually the right thing to do - in the outermost select list.
I'm not quite sure why you have an inline view here at all though, or why you're using a subquery to get the count since you're already querying ops_ertchangelog_fact - maybe you want to be using analytic functions here.

SELECT * FROM T_TRANS WHERE TIME_START = to_date('01-09-2014', 'DD-MM-YY');

Sory, I have Question ? Why not show up when I execute some of its field content.
Please help me to fix it. Thank U
SELECT * FROM T_TRANS WHERE TIME_START = to_date('01-09-2014', 'DD-MM-YY');
Oracle is being a bit lenient with you with the date format mask, but you should use YYYY to make it clearer. But you're still providing a single point in time as midnight on that date:
select to_char(to_date('01-09-2014', 'DD-MM-YY'), 'YYYY-MM-DD HH24:MI:SS') as two_digit,
to_char(to_date('01-09-2014', 'DD-MM-YYYY'), 'YYYY-MM-DD HH24:MI:SS') as four_digit
from dual;
TWO_DIGIT FOUR_DIGIT
------------------- -------------------
2014-09-01 00:00:00 2014-09-01 00:00:00
Given the name of the column it's reasonable to assume you have other times, and your query won't match anything except exactly midnight. To find all records on that day, you need to provide a range:
SELECT * FROM T_TRANS
WHERE TIME_START >= to_date('01-09-2014', 'DD-MM-YYYY');
AND TIME_START < to_date('02-09-2014', 'DD-MM-YYYY');
... though I prefer the ANSI date notation for this sort of this:
WHERE TIME_START >= DATE '2014-09-01'
AND TIME_START < DATE '2014-09-02'
You could specify 23:59:59 on the same date, but that will break subtly when you use a timestamp field rather than a date field.
You could also truncate the value from the table (as #San said in a comment), or convert to a string for comparison (as #yammy showed in an answer), but either of those will prevent any index on the time_start column being used, affecting performance.
After reading Alex Poole suggestion, you should try:
SELECT * FROM T_TRANS WHERE to_char(TIME_START, 'DD-MM-YYYY') = '01-09-2014';
Shouldn't the format mask be "DD-MM-YYYY"?

how to catch this 20140205101309 date format?

I wanna catch the date in my table which is written like this "20140205101309" I tried to get by many ways, but i was not able to catch it so how to modifiy my query to catch it ?
select * from my.DETAIL a where A.DATE
between to_DATE('YYYYMMDD hh24:mi:ss','28-dec-2013 12:00:00')
and to_date ('YYYYMMDD hh24:mi:ss','2-feb-2014 00:00:00');
thank you in advance
Make a.call_date a date before comparing:
select *
from operation.reject_detail a
where to_date(a.call_date, 'YYYYMMDDHHMISS') between
to_date('28-12-2013 12:00:00','DD-MM-YYYY HH24:MI:SS') and
to_date('02-02-2014 00:00:00','DD-MM-YYYY HH24:MI:SS' );
Assuming 20140205101309 is: 2014, februari, 5 10:13:09
If you are not interested in the time part do this:
select *
from operation.reject_detail a
where to_date(substr(a.call_date,1,8), 'YYYYMMDD') between
to_date('28-12-2013','DD-MM-YYYY') and
to_date('02-02-2014','DD-MM-YYYY');
Storing dates as strings is bad practice, but since that is what you have and it's in a relatively sensible format, you can just compare it as a string:
select * from my.DETAIL a
where A.DATE between '20131228120000' and '20140202000000'
Or to ignore the time part on the table and include the full second date:
select * from my.DETAIL a
where A.DATE between '20131228000000' and '20140202235959'
There doesn't seem to be much point converting everything to DATE types, particularly if your column is indexed. If it isn't indexed than you could just look at the date part:
where substr(A.DATE, 1, 8) between '20131228' and '20140202'

Resources