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

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

Related

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>

Trying to establish a trigger that counts rows after every update

I have two tables: SKN_ENJIN, and SKN_ENJIN_COUNT
SKN_ENJIN keeps track of usernames and emails.
SKN_ENJIN_COUNT is being used to populate a chart for a dashboard report.
I created this trigger earlier today:
create or replace trigger "BI_SKN_ENJIN_COUNT_TG"
after insert or update or delete on "SKN_ENJIN"
DECLARE
mCount NUMBER;
mDate DATE;
begin
select COUNT(ID) into mCount from SKN_ENJIN where Status = 1;
select TO_DATE(CURRENT_DATE, 'DD-MM-YYYY') into mDate from dual;
MERGE INTO SKN_ENJIN_COUNT c
USING dual d
ON (c.Count_date = mDate)
WHEN MATCHED THEN
UPDATE SET c.Member_count = mCount
WHEN NOT MATCHED THEN
INSERT (Count_date, Member_count)
VALUES (mDate, mCount);
end;
Up until about 10 minutes ago, the trigger worked beautifully. Suddenly, the trigger started throwing ORA-01843: not a valid month
I have tried changing CURRENT_DATE to SYSDATE(), I have tried changing TO_DATE to TO_CHAR. These approaches seemed to cause more errors to appear. What am I missing, and what should I change to solve this problem?
There's no need to call TO_DATE on CURRENT_DATE or SYSDATE. These functions already return DATEs, so there's no need to do any conversion.
In fact, calling TO_DATE on something that is already a DATE forces Oracle to convert it to a string using NLS settings (NLS_DATE_FORMAT) and the convert it back to a date using a given date format picture. If the date format picture you are using does not match NLS_DATE_FORMAT, you will likely end up with errors or incorrect values.
Instead of writing
select TO_DATE(CURRENT_DATE, 'DD-MM-YYYY') into mDate from dual;
you can write
select CURRENT_DATE into mDate from dual;
or just
mDate := CURRENT_DATE;
I don't know what type of the Count_date column in your SKN_ENJIN_COUNT table is, but if it is DATE, it is similarly incorrect to call TO_DATE on it.
I think I found a solution while stumbling my way through it
. It seems that the format of the date is extremely important. Earlier my formatting had been DD-MM-YYYY, when I used MM-DD-YYYY and just a touch of refactoring (ON (TO_DATE(c.Count_date, 'MM-DD-YYYY') = TO_DATE(mDate, 'MM-DD-YYYY')) the script worked without a fuss.
select COUNT(ID) into mCount from SKN_ENJIN where Status = 1;
select sysdate into mDate from dual;
MERGE INTO SKN_ENJIN_COUNT c
USING dual d
ON (TO_DATE(c.Count_date, 'MM-DD-YYYY') = TO_DATE(mDate, 'MM-DD-YYYY'))
WHEN MATCHED THEN
UPDATE SET c.Member_count = mCount

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.

Get days between tow dates

Have a date in the table with format 10/04/14
then use this to_char(nameofcolumn, 'yyyymmdd')) to get this
20140410
Now, need rest a this value the sydate
I use this
select nameofcolumn,
to_char(nameofcolumn, 'yyyymmdd')) - to_char(sysdate, 'yyyymmdd') AS days
from
table;
But te result for example 07/07/14 return 300 days when is 90
Why are you converting these into strings? You can perform basic date arithmetic without converting them:
select nameofcolumn,
nameofcolumn - sysdate AS days
from
table;
I can't add comments so i will post a little addition as a separate answer.
SELECT to_date('07/07/2014','dd/mm/yyyy') - SYSDATE AS days FROM dual;
would return a number with a floating point instead of an integer. You've got to do either
SELECT trunc(to_date('07/07/2014','dd/mm/yyyy') - SYSDATE) AS days FROM dual;
or
SELECT to_date('07/07/2014','dd/mm/yyyy') - trunc(SYSDATE) AS days FROM dual;
depeding on what exactly you want to achieve.

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

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';

Resources