2013-04-24 3 views
0

Я выполняю сравнение нескольких дат в моей хранимой процедуре.Сравнение DateTime в Oracle

TODAY := TO_DATE(TO_CHAR(SYSDATE, 'DD-MON-YYYY') || 
      ' 09:00:00', 'DD-MON-YYYY HH24:MI:SS'); 

    IF PREVIOUS_DATE < TODAY AND 
     TO_DATE(CURRENT_DATE, 'DD-MON-YYYY HH24:MI:SS') >= TODAY THEN 
     -- do something 
    ELSE 
     -- do something else 

Когда я установил CURRENT_DATE = SYSDATE, он не попал в IF части. Может кто-нибудь сказать мне, где я сделал неправильно?

+2

Почему вы сначала конвертируете 'SYSDATE' в символьный литерал, чтобы преобразовать его обратно в' DATE'? Это совершенно бесполезно и из-за того, что формат «MON» связан с отказом в разных средах NLS. 'today: = sysdate' намного безопаснее и правильнее. И преобразование 'CURRENT_DATE', которое является датой' DATE' с использованием 'to_date()', также бесполезно. –

+0

@a_horse_with_no_name Несмотря на то, что я полностью согласен с тем, что «MON» как часть маски формата следует избегать, когда это возможно, в этом случае он должен работать в любой настройке NLS, поскольку OP использует MON последовательно (если не выполняются преобразования «туда и обратно» в другой сессии с разными настройками NLS) - или я ошибаюсь? –

+0

@a_horse_with_no_name извините за параметр CURRENT_DATE, я не заметил, что это функция в oracle, мое фактическое имя параметра - CUR_DATE, просто чтобы было ясно, поэтому я переписываю его с CURRENT_DATE – noobie

ответ

3

"CURRENT_DATE имеет тип VARCHAR2"

Ну что шпигаты моя первая мысль 8-)

Но я думаю, что проблема в вашем использовании CURRENT_DATE. Предполагая, что это функция Oracle, существуют две потенциальные проблемы:

  1. CURRENT_DATE - тип данных DATE и поэтому имеет элемент времени. Нет смысла бросать его на свидание.
  2. CURRENT_DATE возвращает значение, настроенное для системного часового пояса. Вероятно, это точка вашего теста IF. Но знаете ли вы, что такое ценности?

Но это остается простой задачей отладки. Проверьте свои ценности, чтобы понять, что происходит. Вот пример использования DBMS_OUTPUT (AKA The Devil's Debugger), потому что я не знаю, работаете ли вы в среде с лучшими инструментами.

TODAY := trunc(sysdate) + 9/24; 

dbms_output.put_line('TODAY = '||to_char(today, 'DD-MON-YYYY HH24:MI:SS')); 
dbms_output.put_line('PREVIOUS_DATE = '||to_char(previous_date, 'DD-MON-YYYY HH24:MI:SS')); 
dbms_output.put_line('CURRENT_DATE = '||current_date); 


IF PREVIOUS_DATE < TODAY AND 
    to_date(CURRENT_DATE, 'DD-MON-YYYY HH24:MI:SS') >= TODAY 
THEN 
    .... 

Возможно также упростить код одновременно.

Помните, что для просмотра вывода из DBMS_OUTPUT.PUT_LINE вам нужно установить SERVEROUTPUT ON для любого клиента, которого вы используете.


Кстати, это плохая практика объявлять переменные, которые имеют то же имя, что и встроенные модули Oracle. Вот почему это хорошая идея добавить префикс области (l_ для локального, p_ для параметра и т. Д.) К нашим объявлениям. Нам не нужно делать полный венгерский, чтобы получить большую пользу.

+0

'CURRENT_DATE' имеет тип VARCHAR2 и получает входные данные, такие как' 24-APR-2013 16: 15: 17' Кстати, никогда не замечайте функцию trunc перед этим, это упрощает мой код. Благодарю. – noobie

+0

@a_horse_with_no_name - мы можем переопределить CURRENT_DATE Oracle с нашей собственной локальной декларацией. Буйт, как я уже сказал, это плохая практика. – APC

+0

@APC: вы уверены, что можете создать свою собственную функцию, которая не требует использования '()'?Я думаю, что если вы создадите свою собственную функцию с именем 'current_date', единственным способом ее использования будет:' current_date() ' –