CertNote/ 출퇴근 학습 노트
로드맵
SQLD · 개발자SQL 개발자 (SQLD)
  • Week 1
    • 1.데이터 모델링 개요
    • 2.3단계 스키마와 모델링 단계
    • 3.엔터티
    • 4.속성
    • 5.관계
  • Week 2
  • Week 3
    • 1.관계형 DB 와 SELECT
    • 2.문자·숫자 함수
    • 3.날짜·변환 함수
    • 4.NULL 함수와 CASE·DECODE
    • 5.WHERE 절
  • Week 4
  • Week 5
  • Week 6
  • Week 7
  • Week 8
합격 후기

© CertNote · 주간랩스

  • 소개
  • 수정 기록
  • 문의
  • 이용약관
  • 개인정보처리방침
← SQLD/Week 3/Day 3

기준: SQLD 출제 기준·오류 제보

SQLD· AssociateWeek 3 · Day 3읽기 약 6분
핵심 정리
  • Oracle 의 날짜는 일(day) 단위 숫자처럼 계산된다. 날짜 ± 숫자 = 날짜, 날짜 − 날짜 = 일수, 날짜 + 날짜 = 오류.
  • ADD_MONTHS 는 월을 더하고, 말일에서 출발하면 결과도 말일이다. MONTHS_BETWEEN(a, b) 는 a − b 의 개월 수다.
  • TRUNC(날짜, 'MM') 은 그달 1일, ROUND(날짜, 'MM') 은 16일부터 다음 달 1일이 된다.
  • 명시적 변환은 TO_CHAR(→ 문자), TO_DATE(→ 날짜), TO_NUMBER(→ 숫자) 세 가지다.
  • 암시적 변환은 DB 가 알아서 타입을 맞추는 것이다. 결과가 NLS 설정에 따라 달라지므로 명시적 변환이 안전하다.

Day 3 - 날짜·변환 함수

날짜를 숫자처럼 계산한다

Oracle 의 DATE 는 날짜와 시각(시·분·초)을 함께 담는다. 연산의 단위는 1일이다.

연산결과 타입예 → 결과
날짜 + 숫자날짜DATE '2026-11-03' + 7 → 2026-11-10
날짜 − 숫자날짜DATE '2026-11-03' - 3 → 2026-10-31
날짜 − 날짜숫자(일수)DATE '2026-12-25' - DATE '2026-11-03' → 52
날짜 + 숫자/24날짜1/24 일 = 1시간
날짜 + 날짜오류ORA-00975
SELECT DATE '2026-11-03' + 7 AS A, DATE '2026-11-03' - 3 AS B, DATE '2026-12-25' - DATE '2026-11-03' AS C FROM DUAL;
A          B                   C
---------- ---------- ----------
2026-11-10 2026-10-31         52
  • DATE '2026-11-03' 은 날짜 리터럴이다. 형식은 항상 YYYY-MM-DD 이고 NLS 설정과 상관없이 같은 날짜가 된다.
  • 현재 날짜와 시각은 SYSDATE 로 얻는다. 실행할 때마다 값이 바뀌므로, 이 노트의 예제는 고정 날짜와 HIREDATE 를 쓴다.

두 날짜를 더하는 것은 의미가 없어 오류다.

SELECT DATE '2026-11-03' + DATE '2026-11-04' FROM DUAL;
SELECT DATE '2026-11-03' + DATE '2026-11-04' FROM DUAL
                         *
ERROR at line 1:
ORA-00975: date + date not allowed

시각을 더해도 화면에는 날짜만 보일 수 있다. 표시 형식이 YYYY-MM-DD 라서다. 값에는 시각이 들어 있다.

SELECT DATE '2026-11-03' + 1/24 AS PLAIN, TO_CHAR(DATE '2026-11-03' + 1/24, 'YYYY-MM-DD HH24:MI:SS') AS FULL_TIME FROM DUAL;
PLAIN      FULL_TIME
---------- -------------------
2026-11-03 2026-11-03 01:00:00

날짜 함수

함수하는 일결과 타입
ADD_MONTHS(d, n)n개월 뒤(음수면 앞) 날짜날짜
MONTHS_BETWEEN(d1, d2)d1 − d2 의 개월 수숫자
LAST_DAY(d)그달의 마지막 날날짜
NEXT_DAY(d, 요일)d 다음에 오는 그 요일날짜
EXTRACT(YEAR|MONTH|DAY FROM d)연·월·일 한 부분숫자

ADD_MONTHS

SELECT ADD_MONTHS(DATE '2026-01-31', 1) A, ADD_MONTHS(DATE '2026-11-03', -3) B, ADD_MONTHS(DATE '2026-02-28', 1) C FROM DUAL;
A          B          C
---------- ---------- ----------
2026-02-28 2026-08-03 2026-03-31
  • 1월 31일에 한 달을 더하면 2월 31일이 없으므로 2월의 말일(28일)이 된다.
  • 2월 28일은 그달의 말일이다. 말일에서 출발하면 결과도 말일이라 3월 28일이 아니라 3월 31일이다.

MONTHS_BETWEEN

SELECT MONTHS_BETWEEN(DATE '2026-11-03', DATE '2026-08-03') A, MONTHS_BETWEEN(DATE '2026-08-03', DATE '2026-11-03') B, MONTHS_BETWEEN(DATE '2026-11-18', DATE '2026-11-03') C FROM DUAL;
         A          B          C
---------- ---------- ----------
         3         -3 .483870968
  • 앞 날짜에서 뒤 날짜를 뺀다. 순서를 바꾸면 부호가 바뀐다.
  • 개월 수가 딱 떨어지지 않으면 소수가 나온다. 15일 차이는 15 / 31 이라 0.48 정도다.

LAST_DAY, NEXT_DAY, EXTRACT

SELECT LAST_DAY(DATE '2026-02-10') A, LAST_DAY(DATE '2028-02-10') B, NEXT_DAY(DATE '2026-11-03', 'FRIDAY') C FROM DUAL;
A          B          C
---------- ---------- ----------
2026-02-28 2028-02-29 2026-11-06
  • 2028년은 윤년이라 2월 말일이 29일이다.
  • 2026-11-03 은 화요일이다. 다음 금요일은 11-06 이다. 기준일이 그 요일이어도 같은 날이 아니라 다음 주 그 요일이 나온다.
  • 요일 이름은 세션 언어(NLS_DATE_LANGUAGE)를 따른다. 실습장 Oracle 은 AMERICAN 이라 '금요일' 은 ORA-01846 오류이고 'FRIDAY' 를 써야 한다. 한국어 환경이면 반대다.
SELECT ENAME, HIREDATE, EXTRACT(YEAR FROM HIREDATE) Y, EXTRACT(MONTH FROM HIREDATE) M FROM EMP WHERE DEPTNO = 10;
ENAME      HIREDATE            Y          M
---------- ---------- ---------- ----------
CLARK      1981-06-09       1981          6
KING       1981-11-17       1981         11
MILLER     1982-01-23       1982          1
  • EXTRACT 의 결과는 숫자다. 그래서 월이 06 이 아니라 6 으로 나온다. 두 자리 문자로 받으려면 TO_CHAR(HIREDATE, 'MM') 을 쓴다.

날짜에 쓰는 TRUNC 와 ROUND

숫자 함수 TRUNC·ROUND 는 날짜도 받는다. 두 번째 인자가 자릿수 대신 단위다.

호출결과기준
TRUNC(d)그날 0시시각을 버림
TRUNC(d, 'MM')그달 1일일을 버림
TRUNC(d, 'YYYY')그해 1월 1일월·일을 버림
ROUND(d, 'MM')1~15일 → 그달 1일, 16일~ → 다음 달 1일
ROUND(d, 'YYYY')1~6월 → 그해 1월 1일, 7월~ → 다음 해 1월 1일
SELECT TRUNC(DATE '2026-11-18', 'MM') A, TRUNC(DATE '2026-11-18', 'YYYY') B, ROUND(DATE '2026-11-15', 'MM') C, ROUND(DATE '2026-11-16', 'MM') D, ROUND(DATE '2026-07-01', 'YYYY') E FROM DUAL;
A          B          C          D          E
---------- ---------- ---------- ---------- ----------
2026-11-01 2026-01-01 2026-11-01 2026-12-01 2027-01-01

TRUNC(d) 는 시각을 0시로 만든다. 시각이 보이게 찍어 보면 차이가 드러난다.

SELECT TO_CHAR(TO_DATE('2026-11-03 14:35:20', 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI') A, TO_CHAR(TRUNC(TO_DATE('2026-11-03 14:35:20', 'YYYY-MM-DD HH24:MI:SS')), 'YYYY-MM-DD HH24:MI') B FROM DUAL;
A                B
---------------- ----------------
2026-11-03 14:35 2026-11-03 00:00

함수를 섞으면 근속 연수, 수습 종료일, 첫 급여일(입사 달의 말일) 같은 값을 낼 수 있다.

SELECT ENAME, HIREDATE, TRUNC(MONTHS_BETWEEN(DATE '2026-11-03', HIREDATE) / 12) YEARS, ADD_MONTHS(HIREDATE, 6) PROBATION, LAST_DAY(HIREDATE) FIRST_PAY FROM EMP WHERE DEPTNO = 10;
ENAME      HIREDATE        YEARS PROBATION  FIRST_PAY
---------- ---------- ---------- ---------- ----------
CLARK      1981-06-09         45 1981-12-09 1981-06-30
KING       1981-11-17         44 1982-05-17 1981-11-30
MILLER     1982-01-23         44 1982-07-23 1982-01-31

명시적 변환 — TO_CHAR, TO_DATE, TO_NUMBER

              TO_CHAR              TO_DATE
   숫자  ─────────────▶  문자  ─────────────▶  날짜
        ◀─────────────       ◀─────────────
              TO_NUMBER            TO_CHAR

TO_CHAR — 날짜·숫자를 원하는 모양의 문자로

날짜 형식뜻2026-11-03 →
YYYY / YY연 4자리 / 2자리2026 / 26
MM월 2자리11
DD일 2자리03
DAY / DY요일 이름 / 줄임TUESDAY / TUE
Q분기4
HH24, HH, MI, SS시(24시간), 시(12시간), 분, 초
"문자"큰따옴표 안 글자를 그대로"년" → 년
SELECT TO_CHAR(DATE '2026-11-03', 'YYYY"년" MM"월" DD"일"') A, TO_CHAR(DATE '2026-11-03', 'DAY') B, TO_CHAR(DATE '2026-11-03', 'DY') C, TO_CHAR(DATE '2026-11-03', 'Q') D FROM DUAL;
A                   B         C   D
------------------- --------- --- -
2026년 11월 03일    TUESDAY   TUE 4
  • 분은 MI 다. MM 은 월이라, 시각을 HH24:MM 으로 쓰면 분 자리에 월이 찍힌다.
숫자 형식뜻
9숫자 한 자리. 앞의 빈자리는 공백
0숫자 한 자리. 빈자리를 0 으로 채움
, / .천 단위 구분 / 소수점
$달러 기호
L지역 통화 기호(NLS_TERRITORY 에 따라 다름)
SELECT TO_CHAR(1234567.891, '9,999,999.99') A, TO_CHAR(1234567.891, '999,999') B, TO_CHAR(42, '0000') C, TO_CHAR(1234.5, '$9,999.00') D FROM DUAL;
A             B        C     D
------------- -------- ----- ----------
 1,234,567.89 ########  0042  $1,234.50
  • 형식의 자리가 모자라면 값이 잘리는 대신 # 로 채워진다(B).
  • 앞의 공백 한 칸은 부호(+/−) 자리다.

TO_DATE, TO_NUMBER — 문자를 날짜·숫자로

TO_DATE 는 두 번째 인자로 입력 문자열이 생긴 모양을 알려 준다. 출력 모양이 아니다.

SELECT TO_DATE('20261103', 'YYYYMMDD') A, TO_DATE('03/11/2026', 'DD/MM/YYYY') B, TO_NUMBER('1,234', '9,999') + 1 C FROM DUAL;
A          B                   C
---------- ---------- ----------
2026-11-03 2026-11-03       1235

변환할 수 없는 값이면 오류다.

SELECT TO_DATE('2026-13-01', 'YYYY-MM-DD') FROM DUAL;
SELECT TO_DATE('2026-13-01', 'YYYY-MM-DD') FROM DUAL
               *
ERROR at line 1:
ORA-01843: An invalid month was specified.
  • 숫자가 아닌 문자를 TO_NUMBER('ABC') 로 바꾸려 하면 ORA-01722(숫자 변환 실패) 오류가 난다.

암시적 변환과 그 위험

타입이 다른 값끼리 연산·비교하면 Oracle 이 한쪽을 자동으로 바꾼다. 이것이 암시적 변환이다.

SELECT '10' + 5 A, 10 || 5 B, '3' * '4' C FROM DUAL;
         A B            C
---------- --- ----------
        15 105         12
  • 산술 연산자를 만나면 문자를 숫자로 바꾼다('10' + 5 = 15). || 를 만나면 숫자를 문자로 바꾼다(10 || 5 = '105').
  • 숫자 컬럼과 문자를 비교하면(WHERE EMPNO = '7839') 문자 쪽을 숫자로 바꿔 정상 동작한다.

날짜 컬럼과 문자를 비교할 때가 위험하다. 문자를 날짜로 바꿀 때 세션의 NLS_DATE_FORMAT 을 기준으로 삼기 때문이다.

SELECT ENAME, HIREDATE FROM EMP WHERE HIREDATE = '1981-12-03';
ENAME      HIREDATE
---------- ----------
JAMES      1981-12-03
FORD       1981-12-03

같은 날짜를 다른 모양으로 쓰면 실패한다. 03-DEC-81 은 NLS_DATE_FORMAT 이 DD-MON-RR 인 환경에서는 맞는 값이지만, 이 세션(YYYY-MM-DD)에서는 오류다.

SELECT ENAME FROM EMP WHERE HIREDATE = '03-DEC-81';
SELECT ENAME FROM EMP WHERE HIREDATE = '03-DEC-81'
                                       *
ERROR at line 1:
ORA-01858: A non-numeric character was found instead of a numeric character.

⚠️ 암시적 변환에 기대면 같은 SQL 이 환경에 따라 결과가 달라진다. 날짜는 DATE '1981-12-03' 리터럴이나 TO_DATE('1981-12-03', 'YYYY-MM-DD') 처럼 명시적으로 쓴다. 인덱스가 걸린 컬럼 쪽이 변환되면 인덱스를 못 쓰는 성능 문제도 생긴다.

구분명시적 변환암시적 변환
누가 바꾸나사용자가 함수로DB 가 자동으로
예TO_DATE('1981-12-03', 'YYYY-MM-DD')HIREDATE = '1981-12-03'
결과환경과 상관없이 같다NLS 설정에 따라 달라질 수 있다
권장권장피한다

내일은 NULL 을 다른 값으로 바꾸는 NULL 함수와, 조건에 따라 값을 고르는 CASE·DECODE 를 다룬다.

📖 용어

  • DATE 타입 : 날짜와 시각(시·분·초)을 함께 담는 Oracle 타입. 연산 단위는 1일이다.
  • 날짜 리터럴 : DATE 'YYYY-MM-DD' 로 쓰는 날짜 상수. NLS 설정과 상관없이 해석된다.
  • SYSDATE : DB 서버의 현재 날짜와 시각을 돌려주는 함수.
  • NLS 설정 : 날짜 표시 형식, 요일 언어, 통화 기호처럼 나라·언어에 따라 바뀌는 세션 설정.
  • 형식 모델 : 'YYYY-MM-DD', '9,999' 처럼 변환할 모양을 적은 문자열.
  • 명시적 변환 : TO_CHAR·TO_DATE·TO_NUMBER 로 사용자가 타입을 직접 바꾸는 것.
  • 암시적 변환 : 타입이 다른 값을 만났을 때 DB 가 알아서 타입을 맞추는 것.

📝 연습 문제

선택지를 클릭하면 정답·해설이 펼쳐집니다.

문제 1

세션의 날짜 표시 형식이 YYYY-MM-DD 일 때, 다음 SQL 의 결과로 알맞은 것은? ```sql SELECT ADD_MONTHS(DATE '2026-01-31', 1) FROM DUAL; ```

문제 2

다음 중 Oracle 에서 오류가 발생하는 날짜 연산은?

문제 3

다음 SQL 의 결과로 알맞은 것은? ```sql SELECT MONTHS_BETWEEN(DATE '2026-08-03', DATE '2026-11-03') FROM DUAL; ```

문제 4

세션의 날짜 표시 형식이 YYYY-MM-DD 일 때, 다음 SQL 의 결과로 알맞은 것은? ```sql SELECT ROUND(DATE '2026-11-18', 'MM') FROM DUAL; ```

문제 5

다음 중 문자열 '2026-11-03' 을 날짜 타입으로 바꾸는 명시적 변환 함수는?

이전문자·숫자 함수Week 3 · Day 2다음 NULL 함수와 CASE·DECODEWeek 3 · Day 4

참고 공식 자료

  • SQLD 공식 출제 기준(새 탭에서 열림)

이 페이지

  • 날짜를 숫자처럼 계산한다
  • 날짜 함수
  • ADD_MONTHS
  • MONTHS_BETWEEN
  • LAST_DAY, NEXT_DAY, EXTRACT
  • 날짜에 쓰는 TRUNC 와 ROUND
  • 명시적 변환 — TO_CHAR, TO_DATE, TO_NUMBER
  • TO_CHAR — 날짜·숫자를 원하는 모양의 문자로
  • TO_DATE, TO_NUMBER — 문자를 날짜·숫자로
  • 암시적 변환과 그 위험
  • 용어
  • 연습 문제