날짜와 시간
날짜 연산과 MONTHS_BETWEEN, ADD_MONTHS, NEXT_DAY, LAST_DAY 날짜 함수, INTERVAL 리터럴, 두 자리 연도 형식 RR과 YY의 차이, 세션 날짜 형식
#핵심 요약
SYSDATE는 오늘 날짜임
날짜에 숫자를 더하면 그만큼의 일수가 더해지고, 날짜끼리 빼면 일수가 나옴
MONTHS_BETWEEN(최신 날짜, 예전 날짜)는 개월 수, ADD_MONTHS(날짜, n)는 n개월 뒤, NEXT_DAY(날짜, '요일')는 그 뒤 첫 요일, LAST_DAY(날짜)는 그 달의 마지막 날임
두 자리 연도를 YY로 해석하면 항상 현재 연도와 같은 세기가 됨RR은 지정한 두 자리와 현재 연도의 끝 두 자리에 따라 세기가 달라짐
날짜 문자열 비교는 세션의 NLS_DATE_FORMAT에 따라 결과가 달라짐
#개념과 동작 원리
RR 해석 규칙:
| 지정한 두 자리 연도 | 현재 연도 끝 두 자리 00~49 | 현재 연도 끝 두 자리 50~99 |
|---|---|---|
| 00~49 | 현재와 같은 세기 | 현재 세기 + 1 |
| 50~99 | 현재 세기 - 1 | 현재와 같은 세기 |
그래서 현재 연도가 20xx 전반(00~49)이면 RR로 81은 1981, 25는 2025임YY로는 81도 2081이 됨
실습에서 세션 형식을 YY/MM/DD로 바꾸자 hiredate = '81/11/17'이 조회되지 않은 이유가 이것임
MONTHS_BETWEEN(date1, date2): date1이 더 나중이면 양수, 더 이르면 음수임
두 날짜의 일(日)이 같거나 둘 다 그 달의 마지막 날이면 결과는 정수임
그 밖에는 소수가 나올 수 있어 실습에서는 ROUND로 감쌌음
ADD_MONTHS: 결과 타입은 항상 DATE임
날짜가 그 달의 마지막 날이거나, 결과 달의 일수가 원래 일보다 적으면 결과 달의 마지막 날이 됨
NEXT_DAY: 요일 이름은 세션 날짜 언어의 전체 이름이나 약어여야 함
수업 자료처럼 '월요일'은 한국어 날짜 언어 세션에서 쓰는 형태임
INTERVAL 필드 범위:
| 필드 | 범위 |
|---|---|
| YEAR, DAY | 정수, 제한 없음 |
| MONTH | 0~11 |
| HOUR | 0~23 |
| MINUTE | 0~59 |
| SECOND | 0~59.9(N), N은 소수 자릿수 |
실습에서는 INTERVAL YEAR TO MONTH는 년과 월만, INTERVAL DAY TO SECOND는 일부터 초까지 담는다는 점을 OCP 문제로 설명했음
일수 기준 이자 계산처럼 일 단위가 필요하면 DAY TO SECOND를 고른다는 것이 실습의 결론임
#필수 명령어 또는 SQL
#세션 날짜 형식
SELECT * FROM nls_session_parameters;ALTER SESSION SET nls_date_format = 'YY/MM/DD';결과 해석: 바꾼 뒤 WHERE hiredate = '81/11/17'은 문자열이 2081년으로 해석되어 1981년 입사자와 맞지 않음'RR/MM/DD'로 되돌리면 다시 조회됨
세션 설정은 그 세션에만 적용됨
#날짜 연산과 날짜 함수
SELECT SYSDATE FROM dual;
SELECT ename, ROUND(SYSDATE - hiredate)
FROM emp;
SELECT ename, ROUND(MONTHS_BETWEEN(SYSDATE, hiredate))
FROM emp;
SELECT SYSDATE + 100,
ADD_MONTHS(SYSDATE, 100),
SYSDATE + (INTERVAL '100' MONTH)
FROM dual;
SELECT NEXT_DAY(TO_DATE('2025/06/03', 'RRRR/MM/DD'), '월요일'),
LAST_DAY(TO_DATE('2025/06/03', 'RRRR/MM/DD'))
FROM dual;결과 해석:
실습에서는 ADD_MONTHS('2025/06/03', 100)처럼 문자열을 그대로 넣는 문장도 같이 보였음
이 문장은 문자열이 세션 날짜 형식으로 암시적 변환될 때만 동작함TO_DATE로 형식을 지정하는 편이 안전함(형 변환과 날짜 포맷)
실습 업무 문제(답 확인 불가): 계약 만료일(입사 후 100개월), 대출 만기일(오늘부터 36개월), 적금 만기일과 남은 일수(24개월), 다음 수요일 배송 완료일, 30일 뒤 가장 가까운 토요일 마감일, 카드 결제일(이번 달과 다음 달 말일), 이번 달 말일까지 남은 일수
#날짜에서 부분 꺼내기와 INTERVAL
실습 속성 메모에 있는 형태:
SELECT EXTRACT(YEAR FROM hiredate) FROM emp;
SELECT TO_YMINTERVAL('01-02'),
TO_DSINTERVAL('100 10:00:00'),
INTERVAL '1-6' YEAR TO MONTH,
INTERVAL '2 04:30:00' DAY TO SECOND
FROM dual;결과 해석: 개별 실행 출력은 기재 없음
#PostgreSQL 비교
SELECT EXTRACT(YEAR FROM AGE(NOW(), hiredate)) * 12
+ EXTRACT(MONTH FROM AGE(NOW(), hiredate))
FROM emp;
SELECT ename, hiredate, hiredate + (INTERVAL '100' MONTH) "계약 만료일"
FROM emp;결과 해석:
설명: AGE의 MONTH는 전체 개월 수가 아니라 년을 뺀 나머지 월이어서 YEAR * 12와 더함
PostgreSQL에는 LAST_DAY가 없어 실습에서는 DATE_TRUNC('month', $1) + INTERVAL '1 month - 1 day'로 함수를 만들어 썼음
다음 수요일은 EXTRACT(DOW FROM current_date)(일요일 0 ~ 토요일 6)로 계산했음
#사용 조건과 주의사항
NEXT_DAY의 요일 이름은 세션 언어에 따라 바꿔야 함