programing

Oracle: 올바른 월이 아님

padding 2023. 9. 20. 20:09
반응형

Oracle: 올바른 월이 아님

다음 필드가 있는 테이블이 있습니다.

리포트(테이블명) Rep_Date(날짜) Rep_Time(날짜)

Rep_Time 필드에는 '01/01/1753 07:30:00'과 같은 값이 있습니다. 즉, 시간 부분이 해당됩니다.저는 다음과 같은 질문을 작성했습니다.

select Reports.pid, MaxDate from Reports
INNER JOIN (
    select pid, max(TO_DATE(TO_CHAR(REP_DATE, 'DD/MM/YYYY')
        || TO_CHAR(REP_TIME, 'HH24:MI:SS'), 'DD/MM/YYYY HH24:MI:SS')) As MaxDate
    from reports
    group by pid
) ReportMaxDate
on Reports.PID = ReportMaxDate.PID
AND To_Date(To_Char(MaxDate, 'DD/MM/YYYY')) = REP_DATE
WHERE REPORTS.PID=61

쿼리에서 파생된 테이블 부분이 실행되지만 전체 쿼리를 실행하면 "not avalid month"라는 오류가 나타납니다.왜 이러한가?

디버깅을 돕기 위해 다음 쿼리를 실행하면 다음과 같습니다.

select rep_date, rep_time from reports where pid=61 and rownum=1

알겠습니다.

Rep_Date = 01/04/2009
Rep_Time = 01/01/1753 13:00:00

업데이트 15:58 이제 다음 쿼리를 실행할 수 있습니다.

select Reports.pid, MaxDate from Reports
INNER JOIN (
    select pid, max(TO_DATE(TO_CHAR(REP_DATE, 'DD/MM/YYYY')
        || TO_CHAR(REP_TIME, 'HH24:MI:SS'), 'DD/MM/YYYY HH24:MI:SS')) As MaxDate
    from reports group by pid
) ReportMaxDate
on Reports.PID = ReportMaxDate.PID
AND to_date(to_char(maxdate,'MM/DD/YYYY'),'MM/DD/YYYY') = REP_DATE
WHERE REPORTS.PID=61

하지만 나는 한가지 더 추가할 필요가 있습니다.WHEREMaxDate의 시간 부분을 rep_time과 비교하는 절:to_date(to_char(maxdate,'MM/DD/YYYY'),'MM/DD/YYYY') = REP_DATE작동하지 않습니다.

1.

To_Date(To_Char(MaxDate, 'DD/MM/YYYY')) = REP_DATE

문제를 일으키고 있습니다.시간 형식 없이 to_date를 사용하면 Oracle은 현재 세션 NLS 형식을 사용하여 변환합니다. 이 경우 "DD/MM/YYYY"가 아닐 수 있습니다.이거 확인해봐요...

SQL> select sysdate from dual;

SYSDATE
---------
26-SEP-12

Which means my session's setting is DD-Mon-YY

SQL> select to_char(sysdate,'MM/DD/YYYY') from dual;

TO_CHAR(SY
----------
09/26/2012


SQL> select to_date(to_char(sysdate,'MM/DD/YYYY')) from dual;
select to_date(to_char(sysdate,'MM/DD/YYYY')) from dual
               *
ERROR at line 1:
ORA-01843: not a valid month

SQL> select to_date(to_char(sysdate,'MM/DD/YYYY'),'MM/DD/YYYY') from dual;

TO_DATE(T
---------
26-SEP-12

2.

더 중요한 것은, 왜 직접적으로 비교하는 대신에 차로 전환하고 또 데이트로 전환하느냐는 것입니다.

MaxDate = REP_DATE

비교하기 전에 MaxDate의 시간 구성 요소를 무시하려면 다음을 사용해야 합니다.

trunc(MaxDate ) = rep_date

대신.

==Update : 업데이트된 질문을 기반으로 합니다.

Rep_Date = 01/04/2009 Rep_Time = 01/01/1753 13:00:00

문제는 더 복잡하다고 생각합니다. rep_time을 시간으로만 사용하고자 하는 경우 데이터베이스에 날짜로 저장할 수 없습니다.문자열 또는 날짜 대 시간 간격 또는 숫자로 초 단위여야 합니다(알렉스 덕분에 참조). 가능하다면 날짜와 시간을 모두 포함하는 하나의 열 rep_date를 사용하여 최대 날짜 열과 직접 비교하는 것을 제안합니다.

실행 중인 시스템인데 재데이트에 대한 제어권이 없다면 이를 시도해 볼 수 있습니다.

trunc(rep_date) = trunc(maxdate) and 
to_char(rep_date,'HH24:MI:SS') = to_char(maxdate,'HH24:MI:SS')

어느 쪽이든 시간이 잘못 저장되고 있으며(1753년에서 알 수 있듯이) 앞으로 다른 문제가 발생할 수 있습니다.

실제 날짜 형식을 보려면 sysdate를 사용하여 레코드를 삽입합니다.그렇게 하면 실제 날짜 형식을 찾을 수 있습니다.예를들면

insert into emp values(7936, 'Mac', 'clerk', 7782, sysdate, 1300, 300, 10);

이제 삽입된 레코드를 선택합니다.

select ename, hiredate from emp where ename='Mac';

결과는

ENAME   HIREDATE
Mac     06-JAN-13

voila, 당신의 실제 날짜 형식이 발견되었습니다.

ALTER SESSION 명령을 사용하여 세션에 대한 이 데이터베이스 파라미터의 값을 변경하고 원하는 대로 사용할 수도 있습니다.

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-YYYY';
SELECT TO_DATE('05-12-2015') FROM dual;

05/12/2015

'' 안의 형식을 원하는 대로 사용자 지정할 수 있습니다.

table_name에서 TO_CHAR(column_name, 'MONTH-DAY-y') 선택;

언급URL : https://stackoverflow.com/questions/12603975/oracle-not-a-valid-month

반응형