Oracle DATE Vs. SYSDATE Vs. VARCHAR2 0 2 3,021

by psychomem [Oracle 기초] [2017.09.07 10:48:58]


안녕하세요 DB에대해 공부하고 있는 중에 궁금한 사항이 있어 질의를 올리게 되었습니다.

쿼리문은 아래와 같습니다.

 

SELECT 
  B.Year || '-' || B.Gubun || '-' ||  B.Seq as Serial
  , B.NAME
  , A.TERM
  , A.STDATE
  , A.ENDDATE
  , A.RATE
  , A.MNY
  , A.GJ 
  , A.INSCOMPANY
  , A.JNUMBER
FROM
  G_TABLE A, D_TABLE B
WHERE
  A.YEAR = B.YEAR
  AND A.GUBUN = B.GUBUN
  AND A.BUSEO = B.BUSEO
  AND A.SEQ = B.SEQ
  AND TO_DATE(A.ENDDATE, 'YYYYMMDD') <= SYSDATE;

Local에서는 Oracle Client 10g를 이용중이며, Server(host)는 Oracle 8i~11g까지 다양합니다.

 

쿼리를 Toad를 통해 실행하였을 때, 위의 경우 실행이 되는경우가 있고, 안되는 경우가 있습니다.

또한, 마지막 Where절의 AND문(AND TO_DATE(A.ENDDATE, 'YYYYMMDD') <= SYSDATE;)의 부등호 방향을 바꾸면( >=),

ORA-01843 : 지정한 월이 부적합하다는 오류가 발생되고 있습니다.

 

=> ENDDATE의 경우 VARCHAR2형으로 'YYYYMMDD'와 같은 형식으로 날짜를 저장하는데 쓰이는 Column입니다.

 

제가 많이 부족하여... 정확한 원인과 해법을 모르고 있어 이렇게 문의 드리게 되었습니다.

우선 감히 예상하건데,

1. 시, 분에대한 정보가 없는 날짜만으로 SYSDATE와의 비교를 하고자 하여 문제가 발생했는가?

 -> 임의의 시간을 문자열에 추가하여 SYSDATE와 비교해보자.

SELECT TO_DATE(D_TABLE.ENDDATE||'1130', 'YYYYMMDDHH24MI') as TIMES
FROM D_TABLE
WHERE
TO_DATE(D_TABLE.ENDDATE||'1130', 'YYYYMMDDHH24MI') <= SYSDATE;

 -> ORA-01840 : 입력된 값의 길이가 날짜 형식에 비해 부족합니다.

위 쿼리에서 WHERE절을 제하면 DATE에 대해 정상적으로 출력됩니다.

 

2. SYSDATE를 VARCHAR2에 맞춰 문자열로 계산해보자

 -> TO_CHAR()를 이용,

SELECT TO_DATE(D_TABLE.ENDDATE||'1130', 'YYYYMMDDHH24MI') as TIMES
FROM D_TABLE
WHERE
D_TABLE.ENDDATE <= TO_CHAR(SYSDATE, 'YYYYMMDD');

 -> 정상동작. 그러나 서버측 10g, 9i를 제외한 다른버전에서 확인 불가.

 

3. TRUNC를 이용하여 SYSDATE의 날짜정보만을 남겨서 연산을 진행해본다.

 -> SYSDATE를 TRUNC함.

SELECT TO_DATE(D_TABLE.ENDDATE||'1130', 'YYYYMMDDHH24MI') as TIMES
FROM D_TABLE
WHERE
TO_DATE(D_TABLE.ENDDATE, 'YYYYMMDD') <= TRUNC(SYSDATE);

 -> 정상동작. 그러나 서버측 10g, 9i를 제외한 다른버전에서 확인 불가.

=====

위 세가지 방법을 이용하여 '일단' 지금은 동작이 되고 있는 상황입니다.

(일단이라니 전 프로그래머하기엔 참... 문제가 많은것 같습니다 하하;;)

그리고, 대소비교를 하는것이니, TO_NUMBER()를 이용하여 아예 숫자로만 계산을 해야하나도 고민해봤습니다만, 해보진 않았네요...

저 쿼리문을 이용하는 곳은 VB6환경으로, Form의 레이블이나 텍스트박스와 연동하다보니 DATE가 아닌 VARCHAR2를 이용한 듯 보입니다.

이게... 동일한 쿼리문을 사용하는데도 불구하고 클라이언트별로 동작여부가 달라지는 경우가 생겨,

버전의 차이때문인가 하고 조심스레 예상하고 가설을 세워보고 있습니다.

 

명확한 원인도 모른채 함부로 쿼리를 바꾸거나 소스를 수정하기엔 부담이 많이 되고 있어 이렇게 문의드립니다.

DB에 대한 기본적인 이해도 많이 부족한데, DB쪽은 함부로 건들면... 많이 위험하다는 이야기를 들어서 겁도 나고 그렇네요

 

=====

1. 위 쿼리문에서의 문제점

2. 버전에 상관없는 쿼리문을 작성하려면 위 쿼리를 어떻게 바꾸는게 좋을지

3. 저 문제를 이해하고 해결하기위해 제가 어디를 더 찾아보거나 공부해야 하는지

=====

 

위 세가지 중 하나라도 좋으니 조언을 구하고 싶습니다. 긴글 읽어주셔서 감사합니다.

좋은 하루 보내십시요.

by 마농 [2017.09.07 11:20:01]

오류 자료가 존재합니다.
단, 사용 툴에서 부분범위 처리가 되면서
해당 조회 대상(예:토드 500건) 중 오류자료가 포함되는지 여부에 따라
해당 오류가 발생하기도 안하기도 하는 것입니다.
결론은...
오류 자료를 찾아 고쳐야 하는데요.
어차피 컬럼 자체가 문자열이라면?
컬럼을 가공하여 날짜 형식에 맞추기 보다는
조건(sysdate)을 가공하여 컬럼형식에 맞추어 조회하는 것이 바람직합니다.
이러면 에러날 일도 없죠.(성능도 향상)
그래도 오류 자료는 찾아 고쳐주시는게 좋습니다.


by psychomem [2017.09.07 11:27:15]

아! 클라이언트가 DB에 String을 형식에 맞지 않게 집어넣었을꺼란 생각은 못해봤네요!!

Validation을 한번 해주긴 했는데, 흠... 조언 감사드립니다.

'조건을 설계된 칼럼에 맞추는게 바람직하다' <- 이건 잘 알아둬야 겠네요 여러모로 감사드립니다!!

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입