Question

I have a table that has the following data

fromDate | toDate
20JAN11  | 29DEC30

Both dates are for the 21st Century (i.e. 2011 and 2030) but only the last two characters are stored.

Why is the following statement (when run from within a PL/SQL module) against the above data always returns a positive value

dateDifference := (fromDate - toDate)

If i run the following statement from sqlplus i get the correct negative value which is correct.

select to_date('20JAN11','DDMONYY')-to_Date('29DEC30','DDMONYY') from dual;

I remember reading somewhere that Oracle would sometimes use the wrong century but i dont quite remember the exact scenario where that would happen.

Was it helpful?

Solution

Assuming those columns are of DATE datatype, which seems to be the case: Oracle always stores DATE values in an internal format which includes the full year. The fact that you are seeing only a 2-digit year has to do with the date format used to convert the date to a string for display. So most likely the stored century values are not what you think they are.

Try selecting the dates with an explicit format to see what you really have stored:

SELECT TO_CHAR( fromDate, 'DD-MON-YYYY' ), TO_CHAR( toDate, 'DD-MON-YYYY' )

OTHER TIPS

Seems to work for me either way on my 10g database:

SQL> set serveroutput on
SQL> 
SQL> DECLARE
  2    d1   DATE := to_date('20JAN11','DDMONRR');
  3    d2   DATE := to_date('29DEC30','DDMONRR');
  4    diff INTEGER;
  5  BEGIN
  6    diff := d1 - d2;
  7    dbms_output.put_line(diff);
  8  END;
  9  /

-7283

PL/SQL procedure successfully completed

SQL> 

EDIT: works for YY instead of RR year format as well.

EDIT2: Something like this, you mean?

SQL> create table t (d1 date, d2 date);

Table created

SQL> insert into t values (to_date('20JAN11','DDMONYY'), to_date('29DEC30','DDMONYY'));

1 row inserted

SQL> commit;

Commit complete

SQL> 
SQL> DECLARE
  2    R    t%ROWTYPE;
  3    diff INTEGER;
  4  BEGIN
  5    SELECT d1, d2
  6      INTO R
  7      FROM t;
  8    diff := R.d1 - R.d2;
  9    dbms_output.put_line(diff);
 10  END;
 11  /

-7283

PL/SQL procedure successfully completed

SQL> 

As @Alex states, you may want to verify your data.

works without formatting as well

CREATE  TABLE DATETEST(FROMDATE DATE, TODATE DATE);
insert into DATETEST (fromdate,todate) values (to_date('20Jan11','ddMonrr'),to_date('29DEC30','ddMonrr'));

SELECT TO_CHAR(FROMDATE,'ddMonrrrr hh24:mi:ss') FROMDATE, 
       TO_CHAR(TODATE,'ddMonrrrr hh24:mi:ss') TODATE
  from datetest ;

  /*
FROMDATE           TODATE             
------------------ ------------------ 
20Jan2011 00:00:00 29Dec2030 00:00:00 
*/




set serveroutput on
DECLARE 
 l_FROMDATE DATETEST.FROMDATE%type ;
 L_TODATE DATETEST.TODATE%TYPE;
 dateDifference  number;
BEGIN
--notice -- no formatting just putting them into a variable for test
SELECT FROMDATE, TODATE 
    INTO L_FROMDATE, L_TODATE
from datetest;


DATEDIFFERENCE  := L_FROMDATE - L_TODATE ;

  DBMS_OUTPUT.PUT_LINE('DATEDIFFERENCE  = ' || DATEDIFFERENCE  );
end ;

--DATEDIFFERENCE  = -7283

SELECT FROMDATE-TODATE
from datetest ;

/* --still not formatting
FROMDATE-TODATE        
---------------------- 
-7283  
*/


SELECT (FROMDATE - TODATE) DATEDIFF, 
       TO_CHAR(FROMDATE,'ddMonrrrr') FROMDATE, 
       to_char(todate,'ddMonrrrr') todate 
from (
        SELECT TO_DATE('20JAN11','DDMONYY') FROMDATE, 
               TO_DATE('29DEC30','DDMONYY') TODATE 
          FROM DUAL) 
;
/*

DATEDIFF               FROMDATE  TODATE    
---------------------- --------- --------- 
-7283                  20Jan2011 29Dec2030 

*/

try running the first query on your table:

SELECT TO_CHAR(FROMDATE,'ddMonrrrr hh24:mi:ss') FROMDATE, 
       TO_CHAR(TODATE,'ddMonrrrr hh24:mi:ss') TODATE
  from datetest ;

see if the years are what you actually expect.

(Edit: changed to use two digit years)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top