2015-09-02 3 views
0

Может кто-нибудь объяснить мне, почему вывод Query 4 отличается от других, когда запрос 1 возвращает замененные значения, используемые в запросе 2, которые должны совпадать с тем же, что и запрос 4?sql oracle todate difference

Я подозреваю, что это как-то связано с nls_date_format, но я не уверен.

Запрос 1

SELECT TO_DATE(SYSDATE, 'DD/MON/YYYY')FROM DUAL; 
TO_DATE(SYSDATE,'DD/MON/YYYY') 
------------------------------ 
02-SEP-15 

Запрос 2

SELECT TO_DATE('02-SEP-15') - TO_DATE('01/JAN/07') FROM DUAL; 
TO_DATE('02-SEP-15')-TO_DATE('01/JAN/07') 
----------------------------------------- 
            3166 

SELECT TO_DATE(SYSDATE, 'DD/MON/YY') - TO_DATE('01/JAN/2007') FROM DUAL; 

Запрос 3

TO_DATE(SYSDATE,'DD/MON/YY')-TO_DATE('01/JAN/2007') 
--------------------------------------------------- 
               3166 

Запрос 4

SELECT TO_DATE(SYSDATE, 'DD/MON/YYYY') - TO_DATE('01/JAN/2007') FROM DUAL; 

TO_DATE(SYSDATE,'DD/MON/YYYY')-TO_DATE('01/JAN/2007') 
----------------------------------------------------- 
               -72732 

ответ

6

Никогда не звоните to_date по телефону date.

Предполагая, что для вашего nls_date_format установлено значение «DD-MON-RR», то, что похоже на ваш первый запрос, при запуске TO_DATE(SYSDATE, 'DD/MON/YYYY') происходит следующее.

  1. to_date не принимает date в качестве параметра, он принимает только varchar2. Таким образом, Oracle должен делать неявный листинг от date до varchar2, используявашего сеанса.
  2. Это преобразовывает вызов в to_date('02-SEP-15', 'DD/MON/YYYY')
  3. Поскольку ваш входной параметр строки имеет 2-значный год, но ваша маска формата указывает 4-значный год, вы получаете очень неожиданный результат. Вместо того, чтобы интерпретироваться как 2015 год, это интерпретируется как 15-й год (2000 лет назад, когда Римская империя была чем-то вроде этого).
  4. Теперь вы вычитаете 2007 год с 0015 года, и вы получаете разницу чуть более 1 991 года (точнее, 727 321 дней).

Мораль истории - никогда не звоните to_date на date. Это уже date. Преобразование его в date не имеет смысла. Если вы просто хотите установить временную часть date до полуночи, используйте trunc. Не бросайте date в varchar2 назад на номер date.

+0

Только после тестирования этого с помощью набора параметров изменения nls_date_format = 'DD-MM-YYYY'; SELECT TO_DATE (SYSDATE, 'DD/MM/YYYY') - TO_DATE ('01/01/2007 ') FROM DUAL; сделал это, чтобы запрос1 фактически вернул '(00) 15 в год, и, изменив дату nls, это не было бы справедливым сравнением в том, что оно «покажет мне больше», поскольку преобразование полностью отличается. Я понял, что это не лучший запрос для использования, я просто не мог различать возвращаемые типы. –

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