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)연·월·일 한 부분 숫자
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일 이다.
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 정도다.
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(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
날짜 형식 뜻 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 는 두 번째 인자로 입력 문자열이 생긴 모양 을 알려 준다. 출력 모양이 아니다.
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 가 알아서 타입을 맞추는 것.
📝 연습 문제 선택지를 클릭하면 정답·해설이 펼쳐집니다.
세션의 날짜 표시 형식이 YYYY-MM-DD 일 때, 다음 SQL 의 결과로 알맞은 것은?
```sql
SELECT ADD_MONTHS(DATE '2026-01-31', 1) FROM DUAL;
```
A 2026-03-02 B 2026-03-03 C 오류가 발생한다 D 2026-02-28 다음 중 Oracle 에서 오류가 발생하는 날짜 연산은?
A 날짜 + 숫자 B 날짜 + 날짜 C 날짜 − 날짜 D 날짜 − 숫자 다음 SQL 의 결과로 알맞은 것은?
```sql
SELECT MONTHS_BETWEEN(DATE '2026-08-03', DATE '2026-11-03') FROM DUAL;
```
세션의 날짜 표시 형식이 YYYY-MM-DD 일 때, 다음 SQL 의 결과로 알맞은 것은?
```sql
SELECT ROUND(DATE '2026-11-18', 'MM') FROM DUAL;
```
A 2026-12-01 B 2026-11-01 C 2026-11-30 D 2026-11-18 다음 중 문자열 '2026-11-03' 을 날짜 타입으로 바꾸는 명시적 변환 함수는?
A TO_CHAR B TO_NUMBER C EXTRACT D TO_DATE