본문 바로가기
공부/Oracle

오라클 SQL 문법 공부10 - TO_CHAR, TO_DATE, TO_NUMBER

by 리빈아빠 2017. 10. 17.
반응형

서론

이번에는 형변환 함수에 대해서 알아보고자 한다. 문자형, 숫자형, 날짜형 간의 연산을 하기 위해서는 같은 형끼리만 가능한데, 예를들어 VARCHAR2 형태의 속성이라면 값이 10이 들어가더라도 문자 10으로 인식한다. 보통 오라클에서는 WHERE절에 조건을 써 넣을때 COLUMN = 10 이라고 넣으면 COLUMN 컬럼이 문자형이라는 전제하에 묵시적형변환이 되어 자동으로 TO_NUMBER(COLUMN)으로 변경되어 인덱스를 타지도 않고 데이터가 많을 경우 성능이 좋아지지 않는다. 잘 알아두어야 하는 개념이다.

본론

TO_CHAR, TO_NUMBER

--TO_CHAR 함수 (숫자형 -> 문자형으로 변환하기)
--9  9의 개수만큼 자리 수 TO_CHAR(9876, '99999') 9876
--0  0 빈자리를 0으로 채우기 TO_CHAR(9876, '099999') 009876
--$  $ 표시를 붙여서 표시 TO_CHAR(9876, '$99999') $9876
--.  소수점 이하표시         TO_CHAR(9876, '9999.99') 9876.00
--,  천 단위 구분기호를 표시 TO_CHAR(9876, '99,999') 9.876

desc emp2;
select to_char(pay, '999,999') from emp2;
--데이터의 자리수가 크면 안나올 수 있으니 넉넉하게 자리수를 설정해주어야 함-
select to_char(pay, '999,999,999') from emp2;
select max(length(pay)) from emp2;
-- 최대 길이 확인하여 자리수를 설정하면 좋음

--TO_CHAR 함수 (날짜형 -> 문자형으로 변환하기)
--[년도]
--YYYY - 연도를 4자리로 표시
--RRRR - 2000년 이후에 Y2K버그로 인해 등장한 날짜 표기법 연도 4자리
--2000년도 이후의 날짜를 표시하고 싶을때 사용
--YY - 연도를 끝의 2자리마 표시
--RR - 연도를 마지막 2자리만 표시
--YEAR - 연도의 영문 이름

--[월]
--MM - 01~12월 표시
--MONTH, MON - 1~12월 표시

--[일]
--DD - 일을 숫자 2자리로 표시
--DAY - 요일에 해당하는 명칭을 표시. NLS_LANGAGE 에 따라 다름
--DDTH - 몇 번째 날인지를 표시
--WSPTH - 서수 (EX: FOURTH)

--[시간]
--HH24 - 하루를 24시간 표시
--HH - 하루를 12시간 표시
--MI - 분표시
--SS - 초표시

--WW - 1년 기준 몇번째 주인지 표시
--AM ,PM - 오전 오후 표시
--포맷을 소문자로 쓰면 소문자로 표시됨
--Q 분기 (1분기, 2분기, 3분기, 4분기)
alter session set nls_date_language=american;

SELECT SYSDATE,
TO_CHAR(SYSDATE, 'YYYY'),
TO_CHAR(SYSDATE, 'YYYY-MM-DD'),
TO_CHAR(SYSDATE, 'Year'),
TO_CHAR(SYSDATE, 'MON'),
TO_CHAR(SYSDATE, 'DAY'),
TO_CHAR(SYSDATE, 'ddth'),
TO_CHAR(sysdate, 'DDSPTH'),
TO_CHAR(SYSDATE, 'Q')
FROM DUAL;

--89년 이러면 1900년도인지 2000년도인지 모르는데 YYYY로 하면 2000년도로
--RRRR로 하면 1900년도

--직접적으로 TO_NUMBER로 사용하는 경우는 별로 없다
--TO_NUMBER('숫자처럼 생긴문자')
--보통 '2' + 2 이런식으로 하면 TO_NUMBER('2')로 바꿔서 계산 해준다.
--이런걸 보고 묵시적 형변환, 오라클에선 숫자형이 먼저여서 숫자형으로 계산해줌.
--성능상 좋지 않음 비교하고자 하는 컬럼에 함수를 안씌우는것이 최고
--튜닝할때 가장 먼저 체크할 것
SELECT TO_CHAR(NEXT_DAY(ADD_MONTHS(HIREDATE, 6), 2), 'DAY"the" WSPTH "of" MONTH, YYYY') FROM EMP;

보통 쿼리 출력 양식을 변경하거나 조건 절 등에서 비교를 할때 형을 맞춰주기 위해 사용되는 문자형 변환 함수이다.  다른 DBMS에 비해 오라클이 사용하기 편하게 되어있다. TO_NUMBER는 보통 묵시적 형변환이 되기 때문에 자주 사용되진 않지만 명시적으로 표시하는게 성능상 도움이 된다. 그리고 사실 숫자값만 있는 컬럼들은 보통 NUMBER 컬럼이기 때문에 TO_NUMBER까지 할 필요도 없고 아니면 혹시나 VARCHAR2 형태로 숫자 데이터들이 있다 하더라도 문자형 그대로 '2' 이런식으로 비교를 하면 되기 때문에 자주 사용되진 않는다.

TO_DATE

--TO_DATE() 함수
--TO_DATE('날짜 처럼 생긴 숫자 또는 문자', '앞 문자의 날짜형식')
--TO_CHAR에서 사용된 날짜형을 문자형으로 바꾸기의 포맷들이 동일하게 사용된다.
--따로 포맷 지정 안해주면 YYMMDD 순으로 처리함

SELECT TO_DATE('14/12/25', 'RR/MM/DD'),
TO_DATE('14/12/25', 'YY/MM/DD'),
TO_DATE('141225'),
TO_DATE('14/12/25', 'DD/MM/YY')
FROM DUAL;

SELECT SYSDATE - '14/12/15' FROM DUAL;
--날짜형식이 아니므로 당연히 계산 안됨
SELECT SYSDATE - TO_DATE('14/12/15') FROM DUAL;

TO_DATE를 하는 이유는 보통 날짜 계산을 할때 사용하기 위해 변환을 한다.

2017/09/22 - [공부/Oracle] - 오라클 SQL 문법 공부9 - MONTHS_BETWEEN, ADD_MONTHS, NEXT_DAY, LAST_DAY

위의 글의 함수들을 사용하여 정확하게 날짜들을 계산을 하며 가끔 날짜 정보가 VARCHAR2 형태로 데이터가 입력되는 경우들도 있는데 이럴 경우에도 역시 TO_DATE를 사용하여 포맷 변경 후 날짜 연산을 통해 원하는 값을 추출 할 수가 있을 것이다.

TO_CHAR, TO_DATE 정리

--[TO_CHAR 와 TO_DATE 정리]

--날짜의 포맷 변경은 TO_CHAR로 가능하며 이때 TO_CHAR의 첫번째 인수는 반드시 날짜타입
--=> TO_CHAR(날짜, '원하는 날짜 포맷')

--TO_DATE는 날짜처럼 생긴 문자나 숫자를 DB에 날짜 타입으로 인식시켜 날짜연산이나 날짜포맷변경을 할때 주로 사용된다.
--=>TO_DATE('날짜처럼 생긴 문자', '앞 문자의 날짜형식')
--TO_DATE에서의 YY인식 방법
YY < 50 => 20XX
YY >=50 => 19XX

--EX) TO_DATE('01-12-20', 'DD-YY-MM')
--TO_DATE('97-12-20', 'DD-MM-YY') - 에러발생, 97일이 존재하지 않으므로

SELECT TO_DATE('14/12/25'),
       TO_DATE('14/12/25', 'RR/MM/DD')
  FROM DUAL; --1914로 표현 X
  
  
SELECT TO_DATE('14/12/25'),
       TO_DATE('14/12/25', 'YY/MM/DD')
  FROM DUAL; --2050으로 표현 O
  
--YY는 50보다 크면 19로 하고 작으면 20으로 하는걸로 봐서
--값이 적으면 2000년대 근처라고 생각하고 20 붙이는 것 같음
--RR은 무조건 앞에 20 붙이는 것 같다.

실습문제

--문제1) EMP 테이블에서 10번 부서원의 입사 일자를 '1 MAY 1981'와 '1998년 1월 1일'의 형태로 각각 출력하여라*/
select to_char(hiredate, 'DD MON YYYY'),
       to_char(hiredate, 'YYYY"년" MON"월" DD"일"')
  from emp
 where deptno = 10;

--문제2) EMP 테이블에서 20번 부서원의 급여 앞에 $를 삽입하고 3자리마다 , 를 출력하여라*/
select to_char(SAL, '$9,999')
from emp
where deptno = 20;

--문제3) february 22, 1981에 입사한 사원의 이름, 업무, 입사일자를 출력하여라
--nls_date_language=american일 경우
ALTER SESSION SET nls_date_language=american;
select *
from emp
where HIREDATE = TO_DATE('february 22, 1981', 'MM DD, YYYY');

결론

보통 이 문법들은 포맷형태가 기억이 안나서 다시 찾는 경우가 대부분일 것이다. 개념만 기억하고 자주 보면서 익히면 좋을 것 같다.

2017/09/19 - [공부/Oracle] - 오라클 SQL 문법 공부4 - 기본문법 실습

실습문제를 위한 데이터들은 위의 링크에 있다.