Search
moon
sun

09. 함수 ① (문자 · 숫자 · 날짜)

•
SUBSTR · INSTR 의 위치 계산(1부터 시작, 음수는 뒤에서부터) 을 정확히 할 수 있다.
•
ROUND 와 TRUNC 의 차이, 특히 음수 자릿수의 의미를 설명할 수 있다.
•
날짜 연산의 결과 타입(날짜인지 숫자인지)을 예측할 수 있다.
•
함수를 중첩해서 원하는 결과를 만들 수 있다.

1. 함수의 분류와 DUAL

1) 단일행 함수 vs 다중행 함수 ⭐

구분
단일행 함수
다중행 함수(집계 함수)
결과 행 수
입력한 행 수만큼
하나로 묶임
예
UPPER(ENAME)
SUM(SAL)
EMP 14건에 적용하면
14건 출력
1건 출력
사용 위치
SELECT WHERE ORDER BY 등
SELECT HAVING ORDER BY

2) DUAL 테이블이란 ⭐

•
Oracle이 기본 제공하는 1행 1열짜리 더미(dummy) 테이블
•
테이블과 상관없는 계산이나 함수 결과만 확인하고 싶을 때 사용
-- Oracle의 SELECT 문은 FROM 절을 반드시 요구한다. -- 그런데 "1+1이 뭐지?" 처럼 테이블이 필요 없는 계산을 하고 싶을 때가 있다. -- 그때 형식을 맞추기 위해 빌려 쓰는 테이블이 DUAL 이다. SELECT 1 + 1 AS 계산결과 FROM DUAL; -- 테이블이 필요 없지만 FROM 절 형식을 맞추기 위해 사용 -- 계산결과 -- -------- -- 2 → 항상 1행만 나온다
SQL
복사
특징
설명
소유자
SYS (모든 사용자가 사용 가능)
구조
DUMMY 컬럼 1개, 값은 'X' 한 건
용도
계산식·함수 결과 확인, SYSDATE 조회, 시퀀스 값 조회

2. 문자 함수 ⭐⭐

1) 대소문자 변환 — UPPER · LOWER · INITCAP

함수
기능
'smith' 를 넣으면
UPPER(문자)
전부 대문자로
SMITH
LOWER(문자)
전부 소문자로
smith
INITCAP(문자)
첫 글자만 대문자, 나머지 소문자
Smith
-- ============================================================ -- 【이해용 예제】 사원명을 세 가지 형태로 변환 -- ============================================================ SELECT ENAME AS 원본, LOWER(ENAME) AS 소문자, -- 전부 소문자 INITCAP(ENAME) AS 첫글자대문자 -- 첫 글자만 대문자 FROM EMP; -- 원본 소문자 첫글자대문자 -- ------ ------ ------------ -- SMITH smith Smith -- ALLEN allen Allen -- MARTIN martin Martin
SQL
복사
-- ============================================================ -- 【시험용 예제】 08강 숙제 해결 — 대소문자 상관없이 검색하기 ★ -- ============================================================ -- ❌ 08강에서 본 문제 : 데이터는 'SMITH' 인데 'smith' 로 찾으면 0건 SELECT ENAME FROM EMP WHERE ENAME = 'smith'; -- → 0건 -- ✅ 해결 : 컬럼 값을 대문자로 바꿔서 비교한다 SELECT ENAME FROM EMP WHERE UPPER(ENAME) = 'SMITH'; -- ENAME 을 대문자로 변환한 뒤 비교 -- ENAME -- ----- -- SMITH → 1건 ✅ -- ✅ 사용자가 무엇을 입력하든 안전한 형태 (양쪽 모두 대문자로 통일) SELECT ENAME FROM EMP WHERE UPPER(ENAME) = UPPER('sMiTh'); -- → 동일하게 1건 ✅ -- -- ⚠️ 실무 주의: WHERE 절의 컬럼에 함수를 씌우면 그 컬럼의 인덱스를 쓸 수 없어 -- 조회가 느려질 수 있다. (23강 옵티마이저에서 다시 다룹니다)
SQL
복사

2) 길이 — LENGTH

-- ============================================================ -- 【이해용 예제】 이름이 몇 글자인지 세기 -- ============================================================ SELECT ENAME, LENGTH(ENAME) AS 글자수 FROM EMP WHERE LENGTH(ENAME) >= 6; -- 6글자 이상인 사원만 -- ENAME 글자수 -- ------ ------ -- MARTIN 6 -- TURNER 6 -- MILLER 6 → 3건
SQL
복사
함수
세는 단위
'한글' 을 넣으면
LENGTH
글자 수
2
LENGTHB
바이트 수
6 (UTF-8 기준)

3) 문자 잘라내기 — SUBSTR ⭐⭐⭐

SUBSTR(문자열, 시작위치, 길이)
•
시작 위치는 0이 아니라 1부터 시작합니다 ⚠️
•
길이를 생략하면 끝까지
•
시작 위치가 음수면 뒤에서부터 셉니다
문자열 : S M I T H 양수 위치 : 1 2 3 4 5 음수 위치 : -5 -4 -3 -2 -1
Plain Text
복사
식
결과
설명
SUBSTR('SMITH', 1, 3)
SMI
1번째부터 3글자
SUBSTR('SMITH', 3, 2)
IT
3번째부터 2글자
SUBSTR('SMITH', 3)
ITH
길이 생략 → 끝까지
SUBSTR('SMITH', -3, 2)
IT
뒤에서 3번째부터 2글자
SUBSTR('SMITH', -2)
TH
뒤에서 2번째부터 끝까지
SUBSTR('SMITH', 0, 3)
SMI
0은 1과 같게 취급 ⚠️
-- ============================================================ -- 【이해용 예제】 이름의 앞부분과 뒷부분 잘라내기 -- ============================================================ SELECT ENAME, SUBSTR(ENAME, 1, 3) AS 앞3글자, -- 1번째부터 3글자 SUBSTR(ENAME, -2) AS 뒤2글자, -- 뒤에서 2번째부터 끝까지 SUBSTR(ENAME, 2, 2) AS "2~3번째" -- 2번째부터 2글자 FROM EMP; -- ENAME 앞3글자 뒤2글자 2~3번째 -- ------ ------- ------- ------- -- SMITH SMI TH MI -- MARTIN MAR IN AR -- KING KIN NG IN
SQL
복사
-- ============================================================ -- 【시험용 예제】 SUBSTR 로 의미 있는 정보 뽑아내기 ★ -- PLAYER_ID 는 7자리 (예: 2012001) = 앞 4자리가 연도, 뒤 3자리가 일련번호 -- ============================================================ SELECT PLAYER_NAME AS 선수명, PLAYER_ID AS 선수ID, SUBSTR(PLAYER_ID, 1, 4) AS 등록연도, -- 앞 4자리 SUBSTR(PLAYER_ID, 5) AS 일련번호 -- 5번째부터 끝까지 FROM PLAYER WHERE SUBSTR(PLAYER_ID, 1, 4) = '2012'; -- 2012년에 등록된 선수만 -- 선수명 선수ID 등록연도 일련번호 -- ------- ------- -------- -------- -- 김철수 2012001 2012 001 -- 이영희 2012002 2012 002 -- -- ⭐ 시험 포인트 -- SUBSTR의 시작 위치는 '1'부터다. 프로그래밍 언어(0부터)와 달라 가장 많이 틀린다.
SQL
복사

4) 위치 찾기 — INSTR ⭐⭐

INSTR(문자열, 찾을문자 [, 시작위치 [, 몇번째]])
•
찾은 위치(1부터) 를 숫자로 반환
•
못 찾으면 0 을 반환합니다 (NULL이 아님!) ⚠️
식
결과
설명
INSTR('MARTIN', 'A')
2
A가 2번째에 있음
INSTR('SMITH', 'A')
0
A가 없음 → 0 ⚠️
INSTR('ADAMS', 'A')
1
첫 번째 A의 위치
INSTR('ADAMS', 'A', 2)
3
2번째 위치부터 찾음
INSTR('ADAMS', 'A', 1, 2)
3
2번째로 나오는 A
-- ============================================================ -- 【시험용 예제】 INSTR 는 못 찾으면 0을 반환한다 ★★ -- ============================================================ SELECT ENAME, INSTR(ENAME, 'A') AS A의위치 FROM EMP; -- ENAME A의위치 -- ------ ------- -- SMITH 0 ← A가 없다! NULL이 아니라 0 ⚠️ -- ALLEN 1 -- WARD 2 -- MARTIN 2 -- BLAKE 3 -- CLARK 3 -- ADAMS 1 -- 이 성질을 이용해 "특정 문자를 포함한 행"을 찾을 수 있다 SELECT ENAME FROM EMP WHERE INSTR(ENAME, 'A') > 0; -- 위치가 0보다 크다 = 존재한다 -- → ALLEN, WARD, MARTIN, BLAKE, CLARK, ADAMS, JAMES (7건) -- 위와 같은 결과를 LIKE 로도 얻을 수 있다 (08강) SELECT ENAME FROM EMP WHERE ENAME LIKE '%A%'; -- → 동일한 7건 -- ⭐ INSTR 는 '위치까지' 알려주고, LIKE 는 '포함 여부만' 판단한다.
SQL
복사

5) 자리 채우기 — LPAD · RPAD

LPAD(문자열, 전체길이, 채울문자) — 전체 길이가 될 때까지 왼쪽을 채움
-- ============================================================ -- 【이해용 예제】 자리수를 맞춰 정렬된 것처럼 보이게 하기 -- ============================================================ SELECT ENAME, LPAD(ENAME, 10, '*') AS 왼쪽채움, -- 총 10자리가 되도록 왼쪽에 * 채움 RPAD(ENAME, 10, '.') AS 오른쪽채움 -- 총 10자리가 되도록 오른쪽에 . 채움 FROM EMP; -- ENAME 왼쪽채움 오른쪽채움 -- ------ ---------- ---------- -- SMITH *****SMITH SMITH..... -- WARD ******WARD WARD...... -- MARTIN ****MARTIN MARTIN.... -- -- ⚠️ 전체 길이가 원본보다 짧으면 오히려 '잘린다' -- LPAD('MARTIN', 3, '*') → 'MAR'
SQL
복사

6) 공백·문자 제거 — TRIM 계열

💡 EMP · PLAYER 데이터에는 앞뒤 공백이 없어 효과를 볼 수 없으므로, 여기서는 DUAL 로 규칙만 확인합니다.
함수
기능
예
결과
LTRIM(문자열)
왼쪽 공백 제거
LTRIM(' SQL ')
'SQL '
RTRIM(문자열)
오른쪽 공백 제거
RTRIM(' SQL ')
' SQL'
TRIM(문자열)
양쪽 공백 제거
TRIM(' SQL ')
'SQL'
LTRIM(문자열, 제거문자)
왼쪽에서 해당 문자들 제거
LTRIM('xxxSQL', 'x')
'SQL'
TRIM(문자 FROM 문자열)
양쪽에서 한 글자만 지정 가능 ⚠️
TRIM('x' FROM 'xxSQLxx')
'SQL'
-- ============================================================ -- 【시험용 예제】 TRIM 과 LTRIM/RTRIM 의 차이 ★ -- ============================================================ SELECT TRIM(' SQL ') AS 양쪽공백제거, -- 'SQL' LTRIM(' SQL ') AS 왼쪽만, -- 'SQL ' LTRIM('xyxSQL', 'xy') AS 문자집합제거, -- 'SQL' (x,y 를 모두 제거) TRIM('x' FROM 'xxxSQLxxx') AS 특정문자양쪽 -- 'SQL' FROM DUAL; -- 양쪽공백제거 왼쪽만 문자집합제거 특정문자양쪽 -- ------------ ------- ------------ ------------ -- SQL SQL␣␣ SQL SQL -- -- ⚠️ 핵심 차이 -- LTRIM/RTRIM 의 두 번째 인자는 '문자 집합' → 'xy' 를 주면 x 든 y 든 모두 제거 -- TRIM 의 제거 문자는 '딱 한 글자'만 지정 가능 → TRIM('xy' FROM ...) 은 오류
SQL
복사

7) 치환과 결합 — REPLACE · CONCAT

-- ============================================================ -- 【이해용 예제】 특정 문자열을 다른 것으로 바꾸기 -- ============================================================ SELECT JOB AS 원본직무, REPLACE(JOB, 'MAN', '***') AS 치환결과 -- 'MAN' 을 '***' 로 바꿈 FROM EMP; -- 원본직무 치환결과 -- --------- --------- -- CLERK CLERK ← 'MAN' 이 없으면 그대로 -- SALESMAN SALES*** -- MANAGER ***AGER -- PRESIDENT PRESIDENT
SQL
복사
-- ============================================================ -- 【시험용 예제】 CONCAT 은 인자를 딱 2개만 받는다 ★ -- ============================================================ -- ✅ 인자 2개 → 정상 SELECT CONCAT(ENAME, JOB) AS 결합 FROM EMP; -- 결합 -- ------------- -- SMITHCLERK -- ALLENSALESMAN -- ❌ 인자 3개 → 오류 SELECT CONCAT(ENAME, ' - ', JOB) FROM EMP; -- ORA-00909: invalid number of arguments -- ✅ 해결 ① 함수를 중첩한다 SELECT CONCAT(CONCAT(ENAME, ' - '), JOB) AS 결합 FROM EMP; -- 결합 -- ---------------- -- SMITH - CLERK -- ✅ 해결 ② || 를 쓴다 (훨씬 간단) SELECT ENAME || ' - ' || JOB AS 결합 FROM EMP; -- → 동일한 결과 -- -- ⭐ 시험 포인트 -- CONCAT 은 2개, || 는 개수 제한 없음. -- 그리고 둘 다 NULL 을 만나면 '무시' 한다
SQL
복사

3. 숫자 함수 ⭐⭐

1) ROUND 와 TRUNC — 반올림 vs 버림 ⭐⭐⭐

ROUND(숫자, 자릿수) — 지정 자릿수까지 반올림

TRUNC(숫자, 자릿수) — 지정 자릿수까지 무조건 버림

자릿수 눈금 — 이 그림이 핵심입니다
1 2 3 4 . 5 6 7 8 자릿수 지정 : -4 -3 -2 -1 0 1 2 3 4 ↑ 기본값(생략 시 0) = 정수로 만듦
Plain Text
복사
식
ROUND 결과
TRUNC 결과
(1234.5678, 2)
1234.57
1234.56
(1234.5678, 1)
1234.6
1234.5
(1234.5678, 0) 또는 생략
1235
1234
(1234.5678, -1)
1230
1230
(1234.5678, -2)
1200
1200
(1234.5678, -3)
1000
1000
⭐ 음수 자릿수 = 소수점 왼쪽(정수부)을 처리한다-2 는 "십의 자리에서 처리해 백의 자리까지 남긴다"는 뜻입니다.
-- ============================================================ -- 【이해용 예제】 급여를 3으로 나눈 값을 소수 2자리까지 -- ============================================================ SELECT ENAME, SAL, ROUND(SAL / 3, 2) AS 반올림, -- 소수 2자리까지 반올림 TRUNC(SAL / 3, 2) AS 버림 -- 소수 2자리까지 버림 FROM EMP; -- ENAME SAL 반올림 버림 -- ------ ----- -------- -------- -- SMITH 800 266.67 266.66 ← 266.666… 에서 갈린다 -- ALLEN 1600 533.33 533.33 -- JONES 2975 991.67 991.66
SQL
복사
-- ============================================================ -- 【시험용 예제】 음수 자릿수 — 천 단위로 맞추기 ★★ -- ============================================================ SELECT ENAME, SAL, ROUND(SAL, -3) AS "천단위 반올림", TRUNC(SAL, -3) AS "천단위 버림" FROM EMP; -- ENAME SAL 천단위 반올림 천단위 버림 -- ------ ----- ------------- ----------- -- SMITH 800 1000 0 ← 800 은 반올림하면 1000, 버리면 0 -- ALLEN 1600 2000 1000 -- WARD 1250 1000 1000 -- JONES 2975 3000 2000 -- KING 5000 5000 5000 -- -- ⭐ 시험 포인트 -- ROUND(숫자, -N) : 소수점 '왼쪽' N번째 자리에서 반올림 -- TRUNC 는 절대 올라가지 않는다 (800 → 0 이 되는 것에 주의!)
SQL
복사

2) 나머지 — MOD

-- ============================================================ -- 【이해용 예제】 사원번호가 홀수인 사람 찾기 -- ============================================================ SELECT EMPNO, ENAME, MOD(EMPNO, 2) AS 나머지 -- EMPNO 를 2로 나눈 나머지 FROM EMP WHERE MOD(EMPNO, 2) = 1; -- 나머지가 1 = 홀수 -- EMPNO ENAME 나머지 -- ----- ------ ------ -- 7369 SMITH 1 -- 7499 ALLEN 1 -- 7521 WARD 1 -- 7839 KING 1
SQL
복사

3) 올림·내림·절댓값·부호

함수
기능
(-1.5) 를 넣으면
(1.5) 를 넣으면
CEIL(숫자)
올림 (더 큰 정수 쪽)
-1 ⚠️
2
FLOOR(숫자)
내림 (더 작은 정수 쪽)
-2 ⚠️
1
ABS(숫자)
절댓값
1.5
1.5
SIGN(숫자)
부호 (-1 0 1)
-1
1
⚠️ 음수에서 헷갈립니다CEIL(-1.5) 는 -2가 아니라 -1 입니다. "수직선에서 오른쪽" 으로 간다고 기억하세요. FLOOR(-1.5) 는 -2 — 왼쪽으로 갑니다.
-- ============================================================ -- 【시험용 예제】 CEIL / FLOOR 의 음수 처리 ★ -- 테이블에 음수 데이터가 없으므로 DUAL 로 규칙을 확인한다 -- ============================================================ SELECT CEIL(1.5) AS "CEIL(1.5)", -- 2 FLOOR(1.5) AS "FLOOR(1.5)", -- 1 CEIL(-1.5) AS "CEIL(-1.5)", -- -1 ⚠️ FLOOR(-1.5) AS "FLOOR(-1.5)", -- -2 ⚠️ SIGN(-100) AS "SIGN(-100)" -- -1 FROM DUAL; -- CEIL(1.5) FLOOR(1.5) CEIL(-1.5) FLOOR(-1.5) SIGN(-100) -- --------- ---------- ---------- ----------- ---------- -- 2 1 -1 -2 -1
SQL
복사

4. 날짜 함수 ⭐⭐

1) 날짜 연산의 결과 타입 ⭐⭐⭐

연산
결과 타입
의미
날짜 + 3
날짜
3일 후
날짜 - 3
날짜
3일 전
날짜1 - 날짜2
숫자(일수) ⭐
두 날짜의 차이
날짜 + 1/24
날짜
1시간 후 (1일 = 24시간)
날짜1 + 날짜2
❌ 오류
날짜끼리 더할 수 없음
-- ============================================================ -- 【이해용 예제】 입사일 기준으로 날짜 계산하기 -- ============================================================ SELECT ENAME, HIREDATE AS 입사일, HIREDATE + 100 AS "입사 100일 후", -- 날짜 + 숫자 = 날짜 HIREDATE - 7 AS "입사 1주일 전" -- 날짜 - 숫자 = 날짜 FROM EMP WHERE DEPTNO = 10; -- ENAME 입사일 입사 100일 후 입사 1주일 전 -- ------ ---------- ------------- ------------- -- CLARK 1981-06-09 1981-09-17 1981-06-02 -- KING 1981-11-17 1982-02-25 1981-11-10 -- MILLER 1982-01-23 1982-05-03 1982-01-16
SQL
복사
-- ============================================================ -- 【시험용 예제】 날짜 − 날짜 = 숫자 ★★ -- "MILLER 는 KING 보다 며칠 늦게 입사했는가?" -- ============================================================ SELECT SYSDATE AS 오늘, -- 현재 날짜와 시각 SYSDATE - 1 AS 어제, TRUNC(SYSDATE) AS "오늘 0시" -- 시분초를 잘라낸다 FROM DUAL; -- ⚠️ 결과는 실행하는 날짜에 따라 달라집니다 -- 사원별 근속일수 (오늘 - 입사일) SELECT ENAME, HIREDATE AS 입사일, TRUNC(SYSDATE - HIREDATE) AS 근속일수 -- 날짜 - 날짜 = 숫자(일수) FROM EMP WHERE DEPTNO = 10; -- ENAME 입사일 근속일수 -- ------ ---------- -------- -- CLARK 1981-06-09 16478 ← 실행일에 따라 달라짐 -- KING 1981-11-17 16317 -- -- ⭐ 시험 포인트 -- '날짜 - 날짜' 의 결과는 날짜가 아니라 '숫자(일수)' 다. -- 소수점이 나오는 이유는 시분초까지 계산되기 때문 → TRUNC 로 정리한다.
SQL
복사

2) 날짜 전용 함수 4종 ⭐⭐

함수
기능
결과 타입
ADD_MONTHS(날짜, n)
n개월 후(전) 날짜
날짜
MONTHS_BETWEEN(A, B)
A와 B 사이의 개월 수 (A − B)
숫자
NEXT_DAY(날짜, 요일)
그 날짜 이후 가장 가까운 해당 요일
날짜
LAST_DAY(날짜)
그 달의 마지막 날
날짜
-- ============================================================ -- 【이해용 예제】 날짜 함수 4종을 한 번에 -- ============================================================ SELECT ENAME, HIREDATE AS 입사일, ADD_MONTHS(HIREDATE, 6) AS "수습종료(6개월후)", LAST_DAY(HIREDATE) AS "입사월 말일", NEXT_DAY(HIREDATE, '월요일') AS "입사후 첫 월요일" FROM EMP WHERE ENAME IN ('BLAKE', 'SMITH'); -- ENAME 입사일 수습종료(6개월후) 입사월 말일 입사후 첫 월요일 -- ----- ---------- ----------------- ----------- ---------------- -- SMITH 1980-12-17 1981-06-17 1980-12-31 1980-12-22 -- BLAKE 1981-05-01 1981-11-01 1981-05-31 1981-05-04 -- -- ⚠️ NEXT_DAY 의 요일은 DB 언어 설정(NLS_LANGUAGE)을 따른다. -- 한글 환경이면 '월요일', 영어 환경이면 'MONDAY'. -- 숫자로도 지정 가능 : 1=일요일, 2=월요일 … NEXT_DAY(HIREDATE, 2)
SQL
복사
-- ============================================================ -- 【시험용 예제】 MONTHS_BETWEEN 은 '앞 − 뒤' 순서다 ★★ -- 테이블 데이터로는 순서를 대조하기 어려우므로 DUAL 로 규칙을 확인한다 -- ============================================================ SELECT MONTHS_BETWEEN(DATE '2026-07-20', DATE '2026-01-20') AS "뒤가 과거", MONTHS_BETWEEN(DATE '2026-01-20', DATE '2026-07-20') AS "뒤가 미래" FROM DUAL; -- 뒤가 과거 뒤가 미래 -- --------- --------- -- 6 -6 ← 순서를 바꾸면 부호가 뒤집힌다 ⚠️ -- 실제 테이블에 적용 : 사원별 근속 개월 수 SELECT ENAME, HIREDATE AS 입사일, TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE)) AS 근속개월, TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) AS 근속년수 FROM EMP WHERE DEPTNO = 20; -- ENAME 입사일 근속개월 근속년수 -- ------ ---------- -------- -------- -- SMITH 1980-12-17 547 45 ← 실행일에 따라 달라짐 -- SCOTT 1987-07-13 468 39 -- -- ⭐ 시험 포인트 -- MONTHS_BETWEEN(A, B) = A - B (최신 날짜를 앞에 써야 양수) -- 결과는 소수점이 나올 수 있다 → TRUNC 또는 ROUND 로 정리
SQL
복사

3) EXTRACT — 날짜에서 연·월·일 뽑아내기 ⭐⭐

EXTRACT(추출단위 FROM 날짜)
ANSI 표준 함수로, 날짜에서 연도 · 월 · 일 등을 숫자로 뽑아냅니다.
추출 단위
의미
DATE 타입에 사용
YEAR
연도
✅ 가능
MONTH
월
✅ 가능
DAY
일
✅ 가능
HOUR MINUTE SECOND
시·분·초
❌ 불가 — TIMESTAMP 필요 ⚠️
-- ============================================================ -- 【이해용 예제】 입사일에서 연도·월·일을 각각 뽑아내기 -- ============================================================ SELECT ENAME, HIREDATE AS 입사일, EXTRACT(YEAR FROM HIREDATE) AS 입사년, -- 연도만 (숫자) EXTRACT(MONTH FROM HIREDATE) AS 입사월, -- 월만 (숫자) EXTRACT(DAY FROM HIREDATE) AS 입사일자 -- 일만 (숫자) FROM EMP WHERE DEPTNO = 10; -- ENAME 입사일 입사년 입사월 입사일자 -- ------ ---------- ------ ------ -------- -- CLARK 1981-06-09 1981 6 9 -- KING 1981-11-17 1981 11 17 -- MILLER 1982-01-23 1982 1 23 -- -- ⭐ 결과가 '숫자' 이므로 앞에 0이 붙지 않는다 (6월 → 6, 06 아님)
SQL
복사
-- ============================================================ -- 【시험용 예제】 EXTRACT 로 조건 걸기 + 반환 타입 주의 ★★ -- ============================================================ -- 1981년에 입사한 사원만 조회 SELECT ENAME, HIREDATE FROM EMP WHERE EXTRACT(YEAR FROM HIREDATE) = 1981; -- 숫자와 비교 (따옴표 없음!) -- ENAME HIREDATE -- ------ ---------- -- ALLEN 1981-02-20 -- WARD 1981-02-22 -- ... → 10건 -- 12월에 입사한 사원 (연도 무관) SELECT ENAME, HIREDATE FROM EMP WHERE EXTRACT(MONTH FROM HIREDATE) = 12; -- ENAME HIREDATE -- ------ ---------- -- SMITH 1980-12-17 -- JAMES 1981-12-03 -- FORD 1981-12-03 → 3건 -- ❌ 시·분·초는 DATE 타입에서 추출할 수 없다 SELECT EXTRACT(HOUR FROM HIREDATE) FROM EMP; -- ORA-30076: invalid extract field for extract source -- → HOUR/MINUTE/SECOND 는 TIMESTAMP 타입에서만 가능하다 ⚠️ -- ⭐ 시험 포인트 : EXTRACT 는 '숫자'를 반환한다 -- TO_CHAR(HIREDATE, 'YYYY') 는 '문자' 를 반환한다 (10강) -- EXTRACT(YEAR FROM HIREDATE) = 1981 ← 숫자 비교 ✅ -- TO_CHAR(HIREDATE, 'YYYY') = '1981' ← 문자 비교 (따옴표 필요) ✅
SQL
복사
EXTRACT(YEAR FROM 날짜)
TO_CHAR(날짜, 'YYYY') (10강)
반환 타입
숫자
문자
비교할 때
= 1981
= '1981'
월 표기
6 (앞의 0 없음)
'06' (두 자리 유지)
표준 여부
ANSI 표준
Oracle 전용

5. 함수 중첩 ⭐

1) 안쪽부터 실행된다

-- ============================================================ -- 【시험용 예제】 이름 마스킹 처리 — 3중 중첩 ★ -- 목표: 앞 2글자만 남기고 나머지는 * 로 가린다 (길이는 유지) -- ============================================================ SELECT ENAME AS 원본, LENGTH(ENAME) AS 글자수, SUBSTR(ENAME, 1, 2) AS 앞2글자, RPAD( SUBSTR(ENAME, 1, 2), -- ① 앞 2글자를 자르고 LENGTH(ENAME), -- ② 원래 길이만큼 '*' ) -- ③ 나머지를 * 로 채운다 AS 마스킹 FROM EMP; -- 원본 글자수 앞2글자 마스킹 -- ------ ------ ------- -------- -- SMITH 5 SM SM*** -- WARD 4 WA WA** -- MARTIN 6 MA MA**** -- KING 4 KI KI** -- -- ⭐ 함수는 '가장 안쪽부터' 계산된다. 괄호를 짝지어 안에서 밖으로 읽으세요.
SQL
복사

6. 출제 포인트 한눈에 정리

#
꼭 외울 것
핵심
1
단일행 vs 다중행
단일행 = 입력 N행 → 출력 N행
2
DUAL
Oracle의 1행 1열 더미 테이블
3
UPPER LOWER INITCAP
INITCAP = 첫 글자만 대문자
4
SUBSTR 시작 위치
1부터 (0도 1로 취급) ⭐
5
SUBSTR 음수 위치
뒤에서부터 셈
6
SUBSTR 길이 생략
끝까지
7
INSTR 못 찾으면
0 (NULL 아님) ⭐
8
LPAD RPAD
전체 길이가 원본보다 짧으면 잘림
9
LTRIM/RTRIM vs TRIM
LTRIM은 문자 집합, TRIM은 한 글자만
10
CONCAT
인자 2개만 (3개 이상은 ||)
11
ROUND 음수 자릿수
소수점 왼쪽을 처리 (-2 → 백 단위) ⭐
12
TRUNC
절대 올라가지 않음 (버림)
13
CEIL(-1.5) / FLOOR(-1.5)
-1 / -2 ⭐
14
날짜 − 날짜
숫자(일수) ⭐
15
날짜 + 날짜
오류 (불가능)
16
MONTHS_BETWEEN(A,B)
A − B, 순서 바뀌면 부호 반전 ⭐
17
LAST_DAY / NEXT_DAY
그 달 마지막 날 / 이후 첫 해당 요일
18
EXTRACT(YEAR FROM 날짜)
숫자 반환 (TO_CHAR는 문자) ⭐
19
EXTRACT 의 한계
HOUR MINUTE SECOND 는 TIMESTAMP에서만
20
함수 중첩
가장 안쪽부터 실행

7. 확인 문제

Q1. SUBSTR('SQLD', 2, 2) 의 결과는? ① SQ ② QL ③ QLD ④ LD
정답 보기
Q2. SUBSTR('SQLD', -3, 2) 의 결과는?
정답 보기
Q3. INSTR('SMITH', 'A') 의 결과는? ① NULL ② 0 ③ -1 ④ 오류 발생
정답 보기
Q4. ROUND(1234.5678, -2) 와 TRUNC(1234.5678, -2) 의 결과는?
정답 보기
Q5. CEIL(-1.5) 와 FLOOR(-1.5) 의 결과는?
정답 보기
Q6. HIREDATE - HIREDATE 처럼 날짜에서 날짜를 뺀 결과의 데이터 타입은? ① 날짜 ② 숫자 ③ 문자 ④ 오류
정답 보기
Q7. MONTHS_BETWEEN(DATE '2026-01-20', DATE '2026-07-20') 의 결과는?
정답 보기
Q8. EXTRACT(YEAR FROM HIREDATE) 로 1981년 입사자를 찾을 때 옳은 조건은? ① = '1981' ② = 1981 ③ LIKE '1981%' ④ BETWEEN '1981' AND '1981'
정답 보기
Q9. CONCAT(ENAME, ' - ', JOB) 이 오류가 나는 이유와 해결책은?
정답 보기