컴퓨터과학 챕터 2 약 6분

Ch2. SQLD 자격증 — DML 심화와 JOIN 완전 정복

O
OIYO 편집부 기여자
2/4

DML(Data Manipulation Language) 심화

SQLD 2과목의 핵심인 DML은 INSERT, UPDATE, DELETE, SELECT를 모두 포함합니다. 시험에서는 특히 문법의 미묘한 차이실행 결과 예측을 묻습니다.


INSERT 심화

기본 INSERT

-- 단일 행 삽입
INSERT INTO employees (emp_id, name, dept_id, salary)
VALUES (101, '홍길동', 10, 5000000);

-- 전체 컬럼 순서대로 삽입 (컬럼명 생략)
INSERT INTO employees
VALUES (102, '이순신', 20, 6000000, SYSDATE);

서브쿼리를 이용한 다중 행 삽입

-- 다른 테이블에서 데이터를 가져와 삽입
INSERT INTO emp_backup
SELECT emp_id, name, salary
FROM employees
WHERE dept_id = 10;

핵심: INSERT ~ SELECT는 VALUES를 쓰지 않습니다. 컬럼 수와 타입이 일치해야 합니다.


UPDATE 심화

-- 기본 UPDATE
UPDATE employees
SET salary = salary * 1.1
WHERE dept_id = 10;

-- 서브쿼리를 이용한 UPDATE
UPDATE employees
SET salary = (SELECT AVG(salary) FROM employees)
WHERE dept_id = 20;

UPDATE 시 주의사항

-- WHERE 조건이 없으면 전체 행이 변경됨!
UPDATE employees SET salary = 0;  -- 위험!

-- 서브쿼리가 여러 행 반환 시 오류
UPDATE employees
SET dept_id = (SELECT dept_id FROM departments);  -- 오류 (다중 행 반환)

DELETE vs TRUNCATE vs DROP

구분DELETETRUNCATEDROP
종류DMLDDLDDL
WHERE 조건가능불가불가
롤백가능불가 (일부 DB 가능)불가
로그 기록행별 기록최소 로그최소 로그
속도느림빠름빠름
테이블 구조유지유지삭제
AUTO INCREMENT초기화 안 됨초기화 됨
DELETE FROM employees WHERE dept_id = 10;  -- 조건부 삭제
TRUNCATE TABLE employees;  -- 전체 삭제 (빠름)
DROP TABLE employees;  -- 테이블 자체 삭제

JOIN 완전 정복

JOIN은 SQLD에서 가장 많이 출제되는 개념입니다. 각 JOIN 유형의 결과 집합을 정확히 이해해야 합니다.

INNER JOIN (내부 조인)

두 테이블에서 조인 조건을 만족하는 행만 반환합니다.

-- ANSI 표준 문법
SELECT e.name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.dept_id;

-- Oracle 전통 문법
SELECT e.name, d.dept_name
FROM employees e, departments d
WHERE e.dept_id = d.dept_id;

예시 결과:

employees: [A:10, B:20, C:30]
departments: [10:'영업', 20:'개발', 40:'인사']
INNER JOIN → A:영업, B:개발  (30, 40은 제외)

LEFT OUTER JOIN (좌측 외부 조인)

왼쪽 테이블의 모든 행을 반환하고, 오른쪽 테이블에 없으면 NULL.

SELECT e.name, d.dept_name
FROM employees e
LEFT OUTER JOIN departments d ON e.dept_id = d.dept_id;
-- 결과: A:영업, B:개발, C:NULL

RIGHT OUTER JOIN (우측 외부 조인)

오른쪽 테이블의 모든 행을 반환하고, 왼쪽에 없으면 NULL.

SELECT e.name, d.dept_name
FROM employees e
RIGHT OUTER JOIN departments d ON e.dept_id = d.dept_id;
-- 결과: A:영업, B:개발, NULL:인사

FULL OUTER JOIN

양쪽 테이블의 모든 행을 반환, 매칭되지 않으면 NULL.

SELECT e.name, d.dept_name
FROM employees e
FULL OUTER JOIN departments d ON e.dept_id = d.dept_id;
-- 결과: A:영업, B:개발, C:NULL, NULL:인사

CROSS JOIN (교차 조인)

두 테이블의 카티션 곱(모든 조합) — 조인 조건 없음.

SELECT e.name, d.dept_name
FROM employees e
CROSS JOIN departments d;
-- employees 3행 × departments 3행 = 9행

SELF JOIN (자기 참조 조인)

같은 테이블을 두 번 참조합니다.

-- 직원의 매니저 이름 조회
SELECT e.name AS 직원, m.name AS 매니저
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.emp_id;

서브쿼리(Subquery) 완전 정복

단일 행 서브쿼리

서브쿼리가 1개의 값을 반환 → =, >, <, >=, <=, <> 연산자 사용

-- 평균 급여보다 높은 직원 조회
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

다중 행 서브쿼리

서브쿼리가 여러 행을 반환 → IN, ANY, ALL 연산자 사용

-- IN: 특정 부서 직원 중 한 명이라도 일치
SELECT name FROM employees
WHERE dept_id IN (SELECT dept_id FROM departments WHERE location = '서울');

-- ANY: 최소 하나라도 만족
SELECT name FROM employees
WHERE salary > ANY (SELECT salary FROM managers);

-- ALL: 모두 만족
SELECT name FROM employees
WHERE salary > ALL (SELECT salary FROM interns);

상관(Correlated) 서브쿼리

외부 쿼리의 값을 서브쿼리 안에서 참조 — 행마다 서브쿼리 실행

-- 각 직원의 급여가 해당 부서 평균보다 높은 경우
SELECT e.name, e.salary
FROM employees e
WHERE e.salary > (
    SELECT AVG(salary)
    FROM employees
    WHERE dept_id = e.dept_id  -- 외부 쿼리의 dept_id 참조
);

GROUP BY 고급 활용

HAVING vs WHERE

-- WHERE: 그룹화 전 필터
-- HAVING: 그룹화 후 필터 (집계함수 사용 가능)

SELECT dept_id, AVG(salary) AS avg_sal
FROM employees
WHERE hire_date >= '2020-01-01'   -- 행 필터
GROUP BY dept_id
HAVING AVG(salary) > 5000000;     -- 그룹 필터

ROLLUP과 CUBE

-- ROLLUP: 계층적 소계
SELECT dept_id, job_title, SUM(salary)
FROM employees
GROUP BY ROLLUP(dept_id, job_title);
-- dept_id별 소계 + 전체 합계 자동 생성

-- CUBE: 모든 조합의 소계
GROUP BY CUBE(dept_id, job_title);
-- dept_id별, job_title별, 전체 소계 모두 생성

윈도우 함수(Window Function) 기초

SQLD에서 점점 비중이 높아지는 파트입니다.

-- ROW_NUMBER: 고유 순번
SELECT name, salary,
       ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees;

-- RANK: 동점자에게 같은 순위, 다음 순위 건너뜀
-- DENSE_RANK: 동점자에게 같은 순위, 다음 순위 건너뛰지 않음

-- 부서별 급여 순위
SELECT name, dept_id, salary,
       RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS dept_rank
FROM employees;

-- LAG/LEAD: 이전/다음 행 참조
SELECT name, salary,
       LAG(salary, 1) OVER (ORDER BY hire_date) AS prev_salary
FROM employees;

실전 퀴즈 5문항

Q1. 다음 SQL의 결과 행 수는?

SELECT * FROM A CROSS JOIN B;
-- A: 4행, B: 3행
  • ① 3 ② 4 ③ 7 ④ 12

정답: ④ (4 × 3 = 12)


Q2. TRUNCATE와 DELETE의 차이로 옳은 것은?

  • ① TRUNCATE는 WHERE 조건 사용 가능
  • ② DELETE는 롤백 불가능
  • ③ TRUNCATE는 DDL이고 일반적으로 롤백 불가
  • ④ 두 명령어의 실행 속도는 동일

정답: ③


Q3. LEFT OUTER JOIN에서 오른쪽 테이블에 매칭되는 행이 없을 때 반환값은?

  • ① 0 ② 빈 문자열 ③ NULL ④ 오류

정답: ③


Q4. 상관 서브쿼리와 일반 서브쿼리의 가장 큰 차이는?

  • ① 반환 행 수
  • ② 외부 쿼리의 값을 내부에서 참조하는지 여부
  • ③ WHERE 절 사용 여부
  • ④ 집계함수 사용 여부

정답: ②


Q5. HAVING 절에 대한 설명으로 옳은 것은?

  • ① GROUP BY 없이 단독 사용 가능
  • ② 집계함수 결과를 조건으로 사용할 수 있다
  • ③ WHERE 절보다 먼저 실행된다
  • ④ 개별 행을 필터링한다

정답: ②

O

OIYO 편집부

Content Editor

지식 인큐베이터이자 전문 콘텐츠 크리에이터. 경영, 경제, 법률 및 실생활에 유용한 실무/자격증 중심의 깊이 있는 정보를 연구하고 공유합니다.