DML
목차 22
26강이 테이블을 만들고(DDL) 다스리는(DCL) 명령어였다면, 27강은 그 테이블 안의 데이터를 직접 조회·삽입·수정·삭제(DML) 하는 SQL이다. SQL 응용 단원의 킬러 무대 — 점수밭은 SELECT 6절 처리 순서 · WHERE vs HAVING · 집계 함수 NULL 처리 · JOIN 결과 행 수 · 다중행 서브쿼리. 25강 관계대수(SPJD)가 여기서 실제 SQL로 변신한다.
핵심 암기: DML 4종 SIUD(SELECT·INSERT·UPDATE·DELETE) · 처리 순서 프위그해셀오(FROM·WHERE·GROUP BY·HAVING·SELECT·ORDER BY) · 집계 함수 조건은 무조건 HAVING ·
COUNT(*)=NULL 포함 /COUNT(컬럼)=NULL 제외 · σ↔WHERE·π↔SELECT·⋈↔JOIN·÷↔HAVING COUNT · DELETE만 DML·ROLLBACK✅
DML 개요
DML 4종 — SELECT · INSERT · UPDATE · DELETE ·DML 분류·1순위·
[정의] DML(Data Manipulation Language, 데이터 조작어)은 테이블 안의 데이터를 다루는 SQL. 구조(스키마)를 다루는 DDL과 갈린다.
[표] DML 4대 명령어.
| 명령어 | 기능 | 한 줄 |
|---|---|---|
| SELECT | 조회 | 원하는 데이터 검색 |
| INSERT | 삽입 | 새 데이터 추가 |
| UPDATE | 수정 | 기존 데이터 변경 |
| DELETE | 삭제 | 특정 데이터 삭제 |
🔑 암기 SIUD = 셀·인·업·델(SELECT·INSERT·UPDATE·DELETE). DML의 결정적 특성 = ROLLBACK 가능 ✅ — 트랜잭션 단위로 처리돼 되돌릴 수 있다(DDL은 자동 COMMIT이라 ROLLBACK ❌).
⚠️ 함정 ALTER·TRUNCATE·DROP·CREATE는 DDL / GRANT·REVOKE는 DCL / COMMIT·ROLLBACK·SAVEPOINT는 TCL(명령어 종류 표 기준·26강 회색지대). 특히 ALTER·TRUNCATE를 DML로 착각하는 함정이 단골.
🎯 빈출 "DML 명령어가 아닌 것" — ALTER 같은 DDL 한 개를 섞어 오답 유도. 거의 매회.
💡 보충 21강 정조제 회수 — 정(DDL)·조(DML·27강)·제(DCL)·트(TCL). 26강의 DELETE vs TRUNCATE도 결국 "DELETE만 DML" 한 줄로 갈린다.
SELECT — 데이터 조회
SELECT 6절 구조와 FROM 절 ·SELECT 구조·
[정의] SELECT는 DML에서 가장 복잡한 명령어. 6개 절로 이루어지고, 작성 순서는 아래 고정이다(★실행 순서는 다름 — 처리 순서 카드에서★).
SELECT 컬럼명 -- 조회할 컬럼
FROM 테이블명 -- 대상 테이블
WHERE 조건 -- 행 필터링
GROUP BY 그룹화컬럼 -- 그룹화 기준
HAVING 그룹조건 -- 그룹 필터링
ORDER BY 정렬컬럼 [ASC|DESC] -- 정렬
[표] FROM 절 — 데이터를 가져올 테이블 지정.
| 형태 | 예 | 의미 |
|---|---|---|
| 단일 테이블 | FROM employee |
한 테이블 조회 |
| 다중 테이블 | FROM employee, department |
카티션 곱(25강 ×) |
| 별칭(Alias) | FROM employee e 또는 ... AS e |
긴 테이블명 축약 |
🔑 암기 SELECT * = 모든 컬럼. 별칭은 테이블명 별칭 또는 테이블명 AS 별칭 — 긴 이름을 줄이고 다중 테이블 조인 시 컬럼 출처를 명확히 한다.
🎯 빈출 6절의 작성 순서·별칭 문법. 보통.
💡 보충 FROM employee, department처럼 테이블을 쉼표로 나열하면 25강 카티션 곱(×)이 일어난다 — WHERE로 조인 조건을 걸지 않으면 두 테이블 행 수의 곱만큼 결과가 폭증한다.
WHERE 절 — 비교 · 논리 · 범위 · 패턴 연산자 ·WHERE·1순위·
[정의] WHERE는 조회할 행(튜플)의 조건을 지정. 관계대수의 Select(σ) 에 대응한다(25강).
[표] WHERE 연산자.
| 분류 | 연산자 | 설명 |
|---|---|---|
| 비교 | = <>(≠) > >= < <= |
값 비교 |
| 논리 | AND OR NOT |
조건 결합 |
| 범위 | BETWEEN A AND B |
A 이상 B 이하(양 끝 포함) |
| 목록 | IN (값1, 값2, …) |
목록 중 하나 |
| 패턴 | LIKE '패턴' |
문자열 패턴 매칭 |
[표] LIKE 와일드카드 — 시험 단골.
| 기호 | 의미 |
|---|---|
% |
0개 이상의 임의 문자 |
_ |
정확히 1개의 임의 문자 |
🔑 암기 LIKE '김%' = 김으로 시작 / LIKE '%민%' = 민 포함 / LIKE '김_준' = 3글자·김으로 시작·준으로 끝(_가 정확히 한 글자). BETWEEN 4000 AND 6000 = >= 4000 AND <= 6000(양 끝 포함).
⚠️ 함정 IN ('A','B') = =A OR =B로 같음 / _를 "0개 이상"으로 착각 ❌(→ _는 정확히 1글자, "0개 이상"은 %).
🎯 빈출 LIKE '김_준'의 의미·%/_ 구분. 거의 매회.
WHERE 절 — NULL 처리 ·WHERE NULL·1순위·
[정의] NULL = 값이 존재하지 않음(0이나 공백과 다름). NULL과 어떤 값을 비교해도 결과는 NULL(알 수 없음) 이라, 일반 비교 연산자(=)로는 걸러지지 않는다.
SELECT * FROM employee WHERE dept_code IS NULL; -- NULL인 행
SELECT * FROM employee WHERE dept_code IS NOT NULL; -- NULL 아닌 행
SELECT salary + COALESCE(bonus, 0) FROM employee; -- NULL을 0으로 치환
🔑 암기 NULL 비교는 무조건 IS NULL / IS NOT NULL. NULL이 낀 산술 연산(salary + bonus)은 결과도 NULL — COALESCE나 IFNULL로 치환한다.
⚠️ 함정 WHERE dept_code = NULL ❌(→ 항상 거짓·IS NULL이 정답) / WHERE dept_code == NULL ❌(SQL에 == 없음·문법 오류).
🎯 빈출 NULL 비교 연산자·NULL 산술 결과. 거의 매회(집계 함수 NULL 처리와 짝).
GROUP BY 절 — 행 그룹화 ·GROUP BY·
[정의] GROUP BY는 특정 컬럼 값을 기준으로 행을 묶어 그룹 단위 집계를 가능하게 한다.
SELECT dept_code, COUNT(*) AS 인원수
FROM employee
GROUP BY dept_code;
🔑 암기 SELECT 절에는 GROUP BY에 명시한 컬럼 또는 집계 함수만 올 수 있다. GROUP BY에 없는 일반 컬럼을 SELECT에 쓰면 오류.
⚠️ 함정 SELECT dept_code, emp_name, COUNT(*) … GROUP BY dept_code ❌(→ emp_name이 GROUP BY에 없어 오류). 그룹을 대표하는 값(집계)만 뽑아야 한다.
🎯 빈출 GROUP BY에 없는 컬럼을 SELECT에 쓴 오류 찾기. 보통.
집계 함수 5종 — COUNT · SUM · AVG · MAX · MIN ·집계 함수·1순위·
[정의] 집계 함수(Aggregate Function)는 여러 행을 하나의 값으로 요약한다. GROUP BY와 짝을 이루지만, GROUP BY 없이 전체를 한 그룹으로 집계할 수도 있다.
[표] 5종 + NULL 처리(★시험 핵심★).
| 함수 | 기능 | NULL 처리 |
|---|---|---|
COUNT(*) |
전체 행 수 | NULL 포함해서 셈 |
COUNT(컬럼) |
그 컬럼의 NULL 아닌 값 수 | NULL 제외 |
SUM(컬럼) |
합계 | NULL 무시 |
AVG(컬럼) |
평균 | NULL 제외하고 계산 |
MAX·MIN(컬럼) |
최대·최소 | NULL 무시 |
🔑 암기 COUNT(*)만 NULL 포함(전체 행 수), 나머지(COUNT(컬럼)·SUM·AVG·MAX·MIN)는 NULL 제외. AVG는 NULL을 0으로 보지 않고 분모에서 빼고 계산한다.
⚠️ 함정 COUNT(*) vs COUNT(컬럼) 뒤바꿈 — bonus가 [500, NULL, 300, NULL]이면 COUNT(*)=4·COUNT(bonus)=2. "AVG는 NULL을 0으로 계산" ❌(→ NULL 제외).
🎯 빈출 COUNT(*)/COUNT(컬럼) 결과 수·AVG의 NULL 제외. 거의 매회.
HAVING 절 — WHERE vs HAVING ·HAVING·1순위·
[정의] HAVING은 GROUP BY로 묶인 그룹에 조건을 건다. WHERE가 개별 행을 거른다면, HAVING은 집계된 그룹을 거른다.
[표] WHERE vs HAVING — 가장 헷갈리는 1순위.
| 구분 | WHERE | HAVING |
|---|---|---|
| 적용 대상 | 개별 행(튜플) | 그룹 |
| 위치 | GROUP BY 앞 | GROUP BY 뒤 |
| 집계 함수 | ❌ 사용 불가 | ✅ 사용 가능 |
| 처리 시점 | 그룹화 전 | 그룹화 후 |
SELECT dept_code, COUNT(*) AS 인원수, AVG(salary) AS 평균연봉
FROM employee
WHERE hire_date >= '2020-01-01' -- 개별 행 조건(그룹화 전)
GROUP BY dept_code
HAVING COUNT(*) >= 2; -- 그룹 조건(그룹화 후·집계 함수)
🔑 암기 집계 함수(COUNT·SUM·AVG·MAX·MIN) 조건은 무조건 HAVING. 일반 컬럼 조건은 WHERE. 처리 순서로 보면 WHERE는 그룹화 전(집계값이 아직 없음), HAVING은 그룹화 후(집계값 계산됨) — 집계 조건이 의미 있는 자리는 HAVING뿐.
⚠️ 함정 WHERE COUNT(*) >= 3 ❌(→ HAVING COUNT(*) >= 3) — 집계 함수를 WHERE에 쓰면 문법 오류. 시험에 SQL 한 줄을 주고 "오류 있는 절"을 묻는 형태로 단골 출제.
🎯 빈출 집계 함수 조건의 올바른 절(HAVING)·WHERE/HAVING 위치. 거의 매회.
💡 보충 25강 매핑 — WHERE는 σ(Select·행 거르기) 자리, HAVING은 ÷(Division·"모든" 조건) 계열로 GROUP BY COUNT와 함께 쓰인다.
ORDER BY와 DISTINCT ·정렬·중복 제거·
[정의] ORDER BY = 결과 정렬, DISTINCT = 중복 행 제거. 둘 다 SELECT 결과를 다듬는 절이다.
SELECT * FROM employee ORDER BY salary DESC; -- 내림차순
SELECT * FROM employee ORDER BY dept_code ASC, salary DESC; -- 다중 키
SELECT DISTINCT dept_code FROM employee; -- 중복 제거
🔑 암기 ASC=오름차순(기본값·생략 가능) / DESC=내림차순. ORDER BY 2는 SELECT의 2번째 컬럼 기준 정렬. DISTINCT는 반드시 SELECT 바로 뒤 — 25강 π(Project)의 자동 중복 제거에 대응한다.
⚠️ 함정 SELECT dept_code, DISTINCT … ❌(→ DISTINCT는 SELECT 바로 뒤 한 번만) / "ORDER BY 기본값은 DESC" ❌(→ ASC).
🎯 빈출 ASC/DESC 기본값·DISTINCT 위치. 보통.
★ SELECT 6절 처리 순서 — 프위그해셀오 ★ ·처리 순서·최고 빈출·
[정의] SELECT 문은 작성 순서(SELECT 먼저)와 실제 처리(실행) 순서(FROM 먼저)가 다르다. 이 강 전체에서 가장 자주 나오는 단골이다.
[표] 실행 처리 순서.
| 순서 | 절 | 역할 |
|---|---|---|
| 1 | FROM | 테이블 지정 |
| 2 | WHERE | 행 필터링 |
| 3 | GROUP BY | 그룹화 |
| 4 | HAVING | 그룹 필터링 |
| 5 | SELECT | 컬럼 선택 |
| 6 | ORDER BY | 정렬 |
[흐름] 복합 쿼리 한 줄이 처리되는 길 — 작성은 SELECT부터지만, 엔진은 FROM부터 읽는다.
작성 순서: SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY
처리 순서: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
(1) (2) (3) (4) (5) (6)
테이블 행필터 그룹화 그룹필터 컬럼선택 정렬
🔑 암기 프위그해셀오 — 프롬(FROM)·위어(WHERE)·그룹바이(GROUP BY)·해빙(HAVING)·셀렉트(SELECT)·오더바이(ORDER BY). SELECT가 5번째인 이유 = 어떤 컬럼을 골라낼지는 행이 다 정해진 다음에야 의미가 있어서.
⚠️ 함정 "SELECT가 가장 먼저 처리" ❌(→ 5번째) / "WHERE이 FROM보다 먼저" ❌(→ FROM 없이는 거를 대상이 없음) / "ORDER BY가 GROUP BY보다 먼저" ❌(→ 정렬은 마지막).
🎯 빈출 "각 절이 처리되는 순서로 옳은 것" — 보기 4개 중 프위그해셀오 순서 고르기. 매 회차 1순위.
💡 보충 실전 복합 쿼리도 이 순서로 따라가면 결과가 보인다 — ① FROM으로 데이터 로드 → ② WHERE로 행 거르기 → ③ GROUP BY로 묶기 → ④ HAVING으로 그룹 거르기 → ⑤ SELECT로 컬럼/집계 뽑기 → ⑥ ORDER BY로 정렬.
서브쿼리
서브쿼리 — 단일행 · 다중행 · 위치 ·서브쿼리·1순위·
[정의] 서브쿼리(SubQuery)는 SQL 문 안에 포함된 또 다른 SELECT 문. 바깥 쿼리(메인 쿼리)가 안쪽 쿼리(서브쿼리) 결과를 받아 처리한다.
[표] 반환 행 수에 따른 분류 — 연산자가 갈린다.
| 종류 | 반환 | 연산자 |
|---|---|---|
| 단일행 서브쿼리 | 1행 1열 | = <> > < |
| 다중행 서브쿼리 | 여러 행 | IN · ANY · ALL · EXISTS |
[표] 들어가는 위치별 이름.
| 위치 | 이름 |
|---|---|
| WHERE 절 | 조건 비교(가장 흔함) |
| FROM 절 | 인라인 뷰(Inline View) |
| SELECT 절 | 스칼라 서브쿼리 |
-- 다중행 서브쿼리: 부서별 최고 연봉과 같은 직원
SELECT emp_name, salary
FROM employee
WHERE salary IN (SELECT MAX(salary) FROM employee GROUP BY dept_code);
🔑 암기 단일행 = = 계열 / 다중행 = IN·ANY·ALL·EXISTS. 서브쿼리가 여러 행을 반환하는데 =로 비교하면 오류 — IN을 써야 한다.
⚠️ 함정 다중행 반환 서브쿼리에 단일행 연산자(=) 사용 ❌ / EXISTS는 행의 존재 여부만 보고 참/거짓을 반환(값 비교가 아님).
🎯 빈출 복잡한 중첩 서브쿼리를 주고 반환되는 튜플 수를 묻는 킬러. IN/EXISTS가 핵심.
INSERT · UPDATE · DELETE
INSERT — 데이터 삽입 ·INSERT·
[정의] 테이블에 새 행을 추가하는 명령어. 세 가지 형태가 있다.
-- ① 전체 컬럼에 순서대로
INSERT INTO employee VALUES ('E005', '정다은', 'AI', '사원', 3800);
-- ② 특정 컬럼만(나머지는 DEFAULT/NULL)
INSERT INTO employee (emp_id, emp_name) VALUES ('E006', '최민서');
-- ③ SELECT 결과를 삽입
INSERT INTO employee_backup SELECT * FROM employee WHERE hire_date < '2020-01-01';
🔑 암기 ① 전체 컬럼은 컬럼명 생략 가능(VALUES만) ② 특정 컬럼은 (컬럼…) VALUES (값…) ③ INSERT … SELECT로 다른 테이블 데이터 복사. NOT NULL 컬럼은 반드시 값 제공.
⚠️ 함정 PRIMARY KEY 중복 값 삽입 ❌(개체 무결성 위반) / 컬럼 목록과 VALUES 개수·타입 불일치 ❌.
🎯 빈출 INSERT 3형태 문법·NOT NULL/PK 제약 위반. 보통.
UPDATE — 데이터 수정 ·UPDATE·1순위·
[정의] 기존 행의 값을 변경하는 명령어. SET으로 바꿀 컬럼을, WHERE로 대상 행을 지정한다.
UPDATE employee SET salary = 5000 WHERE emp_id = 'E001';
UPDATE employee SET position = '과장', salary = 6000 WHERE emp_id = 'E002'; -- 다중 컬럼
UPDATE employee SET salary = salary * 1.1; -- WHERE 없음 → 전체 행 인상
🔑 암기 UPDATE 테이블 SET 컬럼=값 [WHERE 조건]. WHERE를 생략하면 모든 행이 수정된다 — 서브쿼리·CASE 식도 SET 값으로 쓸 수 있다.
⚠️ 함정 WHERE 없는 UPDATE = 전체 행 변경(SET salary = 0 → 모든 직원 연봉 0). 실무·시험 모두 단골 경고 포인트.
🎯 빈출 WHERE 유무에 따른 영향 범위·SET 다중 컬럼 문법. 보통.
DELETE — 데이터 삭제 (DELETE vs TRUNCATE) ·DELETE·1순위·
[정의] 테이블에서 행을 삭제하는 DML. WHERE로 특정 행만, 생략 시 전체 행을 지운다(구조는 남음).
DELETE FROM employee WHERE emp_id = 'E001'; -- 조건부 삭제
DELETE FROM employee; -- 전체 행 삭제(구조 유지)
[표] DELETE vs TRUNCATE — 26강 회수.
| 구분 | DELETE | TRUNCATE |
|---|---|---|
| 분류 | DML | DDL |
| WHERE | 가능 ✅ | 불가 |
| ROLLBACK | 가능 ✅ | 불가(자동 COMMIT) |
| 속도 | 느림(행마다 로그) | 빠름 |
🔑 암기 DELETE만 DML → ROLLBACK ✅·WHERE ✅. TRUNCATE는 DDL이라 조건도 못 걸고 되돌릴 수도 없다(가장 빠름). 구조까지 지우려면 DROP(26강).
⚠️ 함정 "DELETE는 DDL" ❌(→ DML·★1순위) / "TRUNCATE는 ROLLBACK 가능" ❌(→ DDL이라 불가) / WHERE 없는 DELETE는 전체 삭제(TRUNCATE와 결과는 같지만 느리고 ROLLBACK 가능).
🎯 빈출 DELETE/TRUNCATE/DROP 자리 바꿔치기·DELETE의 DML/ROLLBACK 특성. 거의 매회.
JOIN과 관계대수 연결
JOIN 종류와 결과 행 수 ·JOIN·최고 빈출·
[정의] JOIN은 둘 이상의 테이블을 공통 컬럼으로 연결해 하나의 결과로 조회한다. 결과 행 수 계산이 3과목 최대 킬러 — 어떤 JOIN이냐에 따라 행 수가 달라진다.
[표] 3대 JOIN.
| 종류 | 결과 | 핵심 |
|---|---|---|
| INNER JOIN | 양쪽에 공통으로 매칭되는 행만 | 매칭 안 되면 탈락 |
| LEFT (OUTER) JOIN | 왼쪽 테이블 전부 + 오른쪽 매칭(없으면 NULL) | 왼쪽은 모두 살아남음 |
| RIGHT (OUTER) JOIN | 오른쪽 테이블 전부 + 왼쪽 매칭(없으면 NULL) | 오른쪽은 모두 살아남음 |
[흐름] 예제 — 직원(3행, 박지호는 부서 NULL) · 부서(3행, 데이터팀은 직원 없음). ON e.dept_code = d.dept_code로 조인.
직원 부서
김민준 · D01 D01 · 백엔드팀
이서연 · D02 D02 · AI팀
박지호 · (NULL) D03 · 데이터팀(직원 없음)
INNER JOIN → 2행 김민준-백엔드팀, 이서연-AI팀 (NULL·데이터팀 탈락)
LEFT JOIN → 3행 + 박지호-NULL (직원 전부 살아남음)
RIGHT JOIN → 3행 + NULL-데이터팀 (부서 전부 살아남음)
🔑 암기 INNER = 교집합(매칭만) / LEFT = 왼쪽 전부 / RIGHT = 오른쪽 전부. 행 수는 INNER(매칭 수) ≤ OUTER(전부 + 매칭). FROM A, B WHERE A.x=B.x는 INNER JOIN과 같다.
⚠️ 함정 매칭 안 되는 행(부서 NULL·직원 없는 부서)의 처리 — INNER는 버리고, OUTER는 NULL로 채워 살린다. 한 부서에 직원이 여럿이면 그 수만큼 행이 늘어난다(행 수 계산 시 매칭 개수 주의).
🎯 빈출 두 테이블을 주고 JOIN 결과 행 수·NULL 포함 여부를 묻는 킬러. INNER/LEFT/RIGHT 행 수 차이가 핵심. 거의 매회.
💡 보충 24강 student ⋈ enrollment ⋈ course 다중 조인이 그대로 SQL 3-테이블 JOIN으로 이어진다 — 연결 테이블(enrollment)을 가운데 두고 양쪽 FK로 묶는다.
SPJD ↔ SQL 매핑 — 25강 관계대수의 SQL 변신 ·관계대수↔SQL·1순위·
[정의] 25강 순수 관계 연산자 SPJD(셀프조디) 가 27강 SQL로 본격 변신하는 종합 무대. 시험은 "σ에 대응하는 SQL 절은?" 식으로 매핑을 직접 묻는다.
[표] SPJD ↔ SQL.
| 관계대수 | 기호 | SQL |
|---|---|---|
| 셀렉트(Select) | σ | WHERE 절 |
| 프로젝트(Project) | π | SELECT 절(정확히는 SELECT DISTINCT) |
| 조인(Join) | ⋈ | JOIN … ON(또는 FROM A,B WHERE A.x=B.x) |
| 디비전(Division) | ÷ | GROUP BY … HAVING COUNT ("모든" 조건) |
🔑 암기 셀(σ)·프(π)·조(⋈)·디(÷) = WHERE·SELECT·JOIN·HAVING COUNT. σ=행 거르기는 WHERE, π=열 뽑기는 SELECT절, ÷="모든"은 HAVING COUNT로 구현된다.
⚠️ 함정 단어 SELECT가 같다고 σ↔SELECT절로 매칭하면 함정 — σ는 WHERE, SELECT절은 π다. "÷ ↔ ORDER BY" ❌(→ HAVING COUNT) / "π ↔ FROM" ❌(→ SELECT절).
🎯 빈출 관계대수 연산자 ↔ SQL 절 대응. 거의 매회(25강과 교차).
기출 다지기
[기출 1 출제] SQL SELECT 문의 각 절이 처리(실행)되는 순서로 옳은 것은?
- ① SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY
- ② FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
- ③ FROM → SELECT → WHERE → GROUP BY → HAVING → ORDER BY
- ④ WHERE → FROM → GROUP BY → SELECT → HAVING → ORDER BY
정답 및 해설 보기
정답 ②
처리 순서 = 프위그해셀오 = FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY.
| 선지 | 판정 |
|---|---|
| ① | SELECT가 먼저 → ❌(SELECT는 5번째) |
| ② | 프위그해셀오 → 정답 |
| ③ | SELECT가 WHERE 앞 → ❌ |
| ④ | WHERE가 FROM 앞 → ❌(FROM이 항상 1번째) |
🔑 가장 자주 틀리는 함정 = "SELECT가 맨 먼저 처리된다"는 착각. 실제로는 5번째.
[기출 2 출제] 다음 SQL 문에서 문법적 오류가 있는 절은?
SELECT dept_code, COUNT(*) AS cnt -- (1)
FROM employee -- (2)
WHERE COUNT(*) >= 3 -- (3)
GROUP BY dept_code; -- (4)
- ① (1)
- ② (2)
- ③ (3)
- ④ (4)
정답 및 해설 보기
정답 ③ (3)
WHERE 절에는 집계 함수를 쓸 수 없다. COUNT(*) 같은 집계 조건은 반드시 HAVING에.
| 절 | 판정 |
|---|---|
| (1) SELECT | 정상 |
| (2) FROM | 정상 |
| (3) WHERE COUNT(*) | 정답(오류) — 집계 함수는 WHERE 불가 |
| (4) GROUP BY | 정상 |
🔑 올바른 형태 = … GROUP BY dept_code HAVING COUNT(*) >= 3. 집계 조건은 HAVING.
[기출 3 출제] 다음 SQL의 실행 결과로 옳은 것은?
[employee 테이블]
emp_id | emp_name | bonus
E001 | 김민준 | 500
E002 | 이서연 | NULL
E003 | 박지호 | 300
E004 | 최예린 | NULL
SELECT COUNT(*), COUNT(bonus) FROM employee;
- ① 4, 4
- ② 4, 2
- ③ 2, 2
- ④ 2, 4
정답 및 해설 보기
정답 ② (4, 2)
COUNT(*)= 전체 행 수 = 4(NULL 포함)COUNT(bonus)= bonus가 NULL 아닌 값의 수 = 2(E001·E003만)
🔑 COUNT(*) → NULL 포함(전체 행) / COUNT(컬럼) → NULL 제외(값 있는 행만). 이 차이가 핵심.
[기출 4 출제] 다음 SQL의 의미로 옳은 것은?
SELECT * FROM employee WHERE emp_name LIKE '김_준';
- ① 이름이 '김준'인 직원
- ② 이름이 '김'으로 시작하고 '준'으로 끝나는 3글자 이름의 직원
- ③ 이름에 '김'과 '준'이 포함된 직원
- ④ 이름이 '김준'을 포함하는 직원
정답 및 해설 보기
정답 ②
_는 정확히 1글자의 임의 문자. '김_준' = 김 + 임의 1글자 + 준 = 정확히 3글자.
| 기호 | 의미 |
|---|---|
% |
0개 이상 임의 문자 |
_ |
정확히 1개 임의 문자 |
🔑 김민준·김서준·김하준 등이 해당. _를 %(0개 이상)와 혼동하면 함정.
[기출 5 출제] DML(Data Manipulation Language) 명령어가 아닌 것은?
- ① INSERT
- ② UPDATE
- ③ ALTER
- ④ DELETE
정답 및 해설 보기
정답 ③ ALTER
DML = SELECT · INSERT · UPDATE · DELETE(SIUD).
| 선지 | 분류 | 판정 |
|---|---|---|
| ① INSERT | DML | 맞음 |
| ② UPDATE | DML | 맞음 |
| ③ ALTER | DDL(구조 변경) | 정답 |
| ④ DELETE | DML | 맞음 |
🔑 ALTER·TRUNCATE·DROP·CREATE는 DDL. DML에 섞인 DDL 한 개를 골라내는 단골 함정.
[기출 6 출제] 다음 SQL의 실행 결과로 옳은 것은?
[score 테이블]
student_id | subject | score
S001 | 수학 | 90
S001 | 영어 | 80
S002 | 수학 | 70
S002 | 영어 | 85
S003 | 수학 | 95
SELECT subject, AVG(score) AS 평균점수
FROM score
GROUP BY subject
HAVING AVG(score) >= 82
ORDER BY 평균점수 DESC;
- ① 수학 85, 영어 82.5
- ② 영어 82.5, 수학 85
- ③ 수학 85
- ④ 영어 82.5
정답 및 해설 보기
정답 ①
프위그해셀오 순서로 추적.
| 단계 | 처리 |
|---|---|
| FROM·WHERE | score 5행 로드(WHERE 없음) |
| GROUP BY | 수학(90·70·95) / 영어(80·85) |
| HAVING | 수학 평균 (90+70+95)/3 = 85 ✅ / 영어 (80+85)/2 = 82.5 ✅ — 둘 다 82 이상 통과 |
| SELECT·ORDER BY | 평균점수 DESC → 수학 85, 영어 82.5 |
🔑 두 그룹 모두 HAVING 통과 후 내림차순 정렬 → 수학(85)이 영어(82.5)보다 앞.
[기출 7 출제] 다음 두 테이블을 INNER JOIN했을 때 결과 행의 수는? (조인 조건: 사원.부서코드 = 부서.부서코드)
[사원] [부서]
이준호 · D01 D01 · 개발팀
김서연 · D01 D02 · 기획팀
박도윤 · D02 D03 · 디자인팀
최유나 · (NULL)
정시우 · D04
- ① 2
- ② 3
- ③ 4
- ④ 5
정답 및 해설 보기
정답 ② 3
INNER JOIN = 양쪽에 매칭되는 행만.
| 사원 | 부서코드 | 매칭 | 결과 |
|---|---|---|---|
| 이준호 | D01 | ✅ 개발팀 | 포함 |
| 김서연 | D01 | ✅ 개발팀 | 포함 |
| 박도윤 | D02 | ✅ 기획팀 | 포함 |
| 최유나 | NULL | ❌ | 탈락 |
| 정시우 | D04 | ❌(부서에 D04 없음) | 탈락 |
→ D01 매칭 2행 + D02 매칭 1행 = 3행. D03(디자인팀)은 직원이 없어 INNER 결과에 없음.
🔑 INNER는 매칭만 — NULL·매칭 실패 행은 탈락. 한 부서에 직원이 여럿이면 그 수만큼 행이 늘어난다(D01이 2행). LEFT JOIN이었다면 최유나·정시우도 NULL로 살아 5행.
[기출 8 출제] 관계대수의 순수 관계 연산자와 대응하는 SQL 구성으로 옳지 않은 것은? (부정형)
- ① Select(σ) ↔ WHERE 절
- ② Project(π) ↔ SELECT 절
- ③ Join(⋈) ↔ JOIN … ON
- ④ Division(÷) ↔ ORDER BY 절
정답 및 해설 보기
정답 ④
Division(÷, "모든" 조건)은 GROUP BY … HAVING COUNT로 구현한다 — ORDER BY(정렬)와 무관.
| 선지 | 판정 |
|---|---|
| ① σ ↔ WHERE | 옳음(행 거르기) |
| ② π ↔ SELECT | 옳음(열 뽑기·DISTINCT) |
| ③ ⋈ ↔ JOIN ON | 옳음 |
| ④ ÷ ↔ ORDER BY | 정답(틀림) — ÷는 HAVING COUNT |
🔑 셀(σ)·프(π)·조(⋈)·디(÷) = WHERE·SELECT·JOIN·HAVING COUNT. 단어 SELECT가 같다고 σ↔SELECT절로 매칭하면 함정(σ는 WHERE, SELECT절은 π).
한 장 요약
| 영역 | 핵심 | 암기팁 |
|---|---|---|
| DML 4종 | SELECT·INSERT·UPDATE·DELETE · ROLLBACK ✅ | SIUD(셀·인·업·델) |
| 처리 순서 | FROM·WHERE·GROUP BY·HAVING·SELECT·ORDER BY | 프위그해셀오(SELECT는 5번째) |
| WHERE 연산자 | 비교·논리·BETWEEN·IN·LIKE | %=0개+·_=정확히 1글자 |
| NULL 처리 | 비교는 IS NULL·산술은 결과 NULL |
= NULL ❌ |
| GROUP BY | 그룹화 컬럼·집계 함수만 SELECT 가능 | 일반 컬럼 SELECT ❌ |
| 집계 함수 | COUNT·SUM·AVG·MAX·MIN | COUNT(*)만 NULL 포함·나머지 제외 |
| WHERE vs HAVING | 행 조건=WHERE / 집계 조건=HAVING | 집계 함수 보이면 무조건 HAVING |
| 서브쿼리 | 단일행== / 다중행=IN·EXISTS |
다중행에 = ❌ |
| INSERT/UPDATE/DELETE | INSERT 3형태 · WHERE 없는 U/D=전체 | DELETE만 DML·ROLLBACK✅ |
| JOIN | INNER(매칭)·LEFT(왼쪽 전부)·RIGHT(오른쪽 전부) | 행 수 = 매칭 개수 주의 |
| SPJD↔SQL | σ·π·⋈·÷ = WHERE·SELECT·JOIN·HAVING COUNT | SELECT절=π(σ 아님) |
🎯 합격 한 끗: 27강은 세 무기면 출제분의 80%가 즉답이다 — ① 프위그해셀오(처리 순서, 매 회차) ② 집계 함수 조건은 무조건 HAVING(COUNT/SUM/AVG/MAX/MIN) ③ JOIN 결과 행 수(INNER=매칭만·OUTER=한쪽 전부+NULL). 여기에 COUNT(*) NULL 포함·LIKE '_' 한 글자·DELETE만 DML(ROLLBACK✅)·SPJD↔SQL 매핑(σ=WHERE·SELECT절=π)만 더 얹으면 끝.
