2011-01-24 8 views
0

У меня есть таблица, которая имеет следующие данныеРазница между двумя датами

fromDate | toDate 
20JAN11 | 29DEC30 

Обе даты являются для 21-го века (то есть 2011 и 2030 г.), но только последние два символа сохраняются.

Почему следующее утверждение (при запуске из в/модуля PL SQL) против приведенных выше данных всегда возвращает положительное значение

dateDifference := (fromDate - toDate) 

Если я запускаю следующее заявление от SQLPLUS я получить правильное отрицательное значение что правильно.

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

Я помню, что читал где-то, что Oracle будет иногда использовать неправильный век, но я довольно не помню точный сценарий, где это будет происходить.

+1

Каков ваш вопрос? Если вы заинтересованы, вставьте/вставьте «20» в строку, но я настоятельно рекомендую изменить тип данных на DATE. –

+0

Я уверен, что там был вопрос (см. 3-е предложение :-)). Тип данных DATE для двух столбцов. Проблема в том, что оператор возвращает положительное значение, если я запускаю его из блока pl/sql. Я знаю, что это сработает, если я назову дату «20», но я попытаюсь выяснить, почему это происходит. Код plsql не использует никакого форматирования, чтобы получить разницу, поэтому у меня был вопрос, что заставляет его делать это. :) – ziggy

+1

Что произойдет с вашей датой, если вы выполните 'alter session set nls_date_format = 'dd mmm yyyy';' и выберите fromDate и toDate? –

ответ

4

Предполагая, что эти столбцы имеют DATE тип данных, который, кажется, так: Oracle всегда хранит DATE значения во внутреннем формате, который включает в себя полный год. Тот факт, что вы видите только 2-значный год, связан с форматом даты, используемым для преобразования даты в строку для отображения. Поэтому, скорее всего, хранящиеся ценности века - это не то, что вы думаете.

Try выбора даты с явным формате, чтобы увидеть то, что вы действительно сохранили:

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

Вы правы. Я проверил данные и хранится в 19-ом столетии как 20-JAN-2011 и 29-DEC-1930 – ziggy

+0

Похоже, проблема связана с исходными данными. Данные, которые были загружены, использовали неправильный век. благодаря – ziggy

2

Кажется, работает для меня в любом случае на моей базе данных 10g:

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: работает YY вместо формата RR года, а также.

EDIT2: Что-то вроде этого, вы имеете в виду?

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> 

Как указано в @Alex, вы можете подтвердить свои данные.

+0

Это отличается тем, что я читаю данные из таблицы и выполняю вычитание без использования каких-либо форматов, если вы используете DDMONRR. Я прочитал данные в курсор и просто использовал значения курсора, например. cursorname.fromDate-cursorName.toDate – ziggy

+0

Похоже, проблема связана с исходными данными. Данные, которые были загружены, использовали неправильный век. Спасибо – ziggy

2

работает без форматирования, а также

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 

*/ 

попробуйте запустить первый запрос на вашем столе:

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

ли годы, что вы на самом деле ожидать.

(Edit: изменен, чтобы использовать две цифры года)

+0

Проверьте значения, которые вы вставили в таблицу. Ваши данные имеют даты 20Jan2011 и 29Dec2030. Данные в таблице, которую я использую, составляют 20Jan11 и 29Dec30. (т. е. год составляет 2 символа) – ziggy

+0

@ziggy, изменено на использование двухзначных лет, одинаковые результаты. – Harrison

Смежные вопросы