1과목
엔터티(Entity) ✅
- 엔터티(Entity)의 정의
- 현실 세계에서 데이터로 관리할 필요가 있는 객체(예: 고객, 주문, 상품 등)
- 엔터티 간 관계에서 “약한 엔터티(Weak Entity)” 란?
- 다른 엔터티의 식별자를 함께 사용해야 구분 가능한 엔터티
- 부모 엔터티의 식별자와 자신의 속성을 결합해 구분된다.(주문-주문상세)
- 강한 엔터티의 식별자 필요
- 엔터티(Entity)와 인스턴스(Instance)의 관계
- 엔터티는 인스턴스의 집합
- 엔터티는 추상적 개념, 인스턴스는 그 실제 데이터를 의미
- 일반화(Generalization)와 특수화(Specialization)에 대한 설명
- 일반화는 하위 엔터티의 공통 속성을 상위 엔터티로 통합하는 것
- 특수화는 반대로 세분화하는 것
- 엔터티(Entity)의 특징
- 반드시 속성을 가진다
- 두 개 이상의 인스턴스를 가진다
- 업무에서 필요로 하는 정보다
- 엔터티 타입을 분류할 때 기준이 되는 것
관계(Relationship) / 관계 차수(Cardinality) ✅
- ‘1:N’
- 하나의 엔터티가 여러 엔터티와 연결(예를 들어 ‘부서 - 사원’)
- “1:N” 관계에서 외래키는 어디에 존재 하는가?
- 자식 엔터티
- “1:N” 관계에서는 ‘N’ 쪽(자식)에 외래키가 존재
- “1:1 관계”
- 한 엔터티의 한 인스턴스가 다른 엔터티의 한 인스턴스와 연결된다(사원 - 사원증)
- 엔터티 간 관계에서 “다대다(N:M)” 관계를 구현할 때 필요한 것
- 조인 테이블(교차 엔터티)
- 다대다 관계는 중간에 별도의 연결 엔터티(Bridge Table, Mapping Table)를 만들어
- 관계(Relationship)의 참여도(Cardinality)를 의미하는 것
ERD ✅
- ERD 구성요소
- ERD 작성 시 관계의 선택성(Optionality) 표시 방법
- 점선과 실선으로 표시
- 선택성은 “점선(선택적)”과 “실선(필수적)”으로 표현하며, 관계 참여 여부를 의미
- “이행적 함수 종속(Transitive Dependency)”
- 학번 → 학과코드 → 학과명
- 학번이 학과코드를 결정하고, 학과코드가 학과명을 결정한다면 학번 → 학과명은 이행적 종속
식별자(Identifier) ✅
- 식별자(Identifier)의 역할
- 식별자는 엔터티의 각 인스턴스를 구분하기 위한 속성 또는 속성들의 조합
- 식별자 관계(Identifying Relationship)의 특징
- 자식 엔터티의 외래키가 기본키 일부가 된다
- 식별자 관계는 부모의 식별자를 자식의 기본키로 포함하는 강한 종속 관계
- 식별자(Identifier) 선정 시 고려할 사항
- 유일성 / 최소성 / 안정성
- 좋은 식별자는 유일하고, 최소이며, 변경 가능성이 낮아야 한다
- 식별자 관계(Identifying)와 비식별자 관계(Non-Identifying)의 가장 큰 차이
- 외래키가 기본키에 포함되는지 여부
- 식별자 관계는 부모의 식별자가 자식의 기본키에 포함되고, 비식별자 관계는 포함되지 않는다.
- 식별자 관계(Identifying)와 비식별자 관계의 구조적 차이
- 식별자 관계는 부모의 키를 자식의 기본키에 포함시킨다
- 식별자 관계는 부모의 식별자가 자식의 기본키 일부로 들어가며, 자식은 독립적으로 존재할 수 없다
- 식별자(Identifier) 선정 기준
- 업무적으로 의미 있는 값이어야 한다
- 식별자는 업무적 의미, 유일성 , 불변성이 중요
- 자주 변경되지 않아야 한다
- 단순해야 한다
- NULL이 없어야 한다
- 중복 X
정규형 ✅
- 제1정규형(1NF)의 조건
- 모든 속성이 원자값(Atomic Value)을 가진다
- 각 속성이 더 이상 분해되지 않는 원자값이어야 한다.
- 원자값 / 반복 속성 제거 / 다중값 제거
- 제2정규형(2NF)의 조건
- 모든 속성이 기본키에 완전 함수 종속되어야 한다
- 2NF는 1NF를 만족하면서 부분 함수 종속이 없는 상태(부분 함수 종속 제거)
- 복합키 중 일부에만 종속된 속성이 있는 경우를 의미한다.
- 제3정규형(3NF)의 조건
- 기본키에 이행적 함수 종속이 존재하지 않는다(이행적 함수 종속을 제거)
- 비주요 속성이 다른 비주요 속성에 종속되지 않아야 한다.
- 모든 결정자가 후보키이다
- BCNF가 3NF보다 더 엄격한 이유
정규화 ✅
- 정규화의 주요 목적
- 데이터의 일관성을 높이고 데이터 중복 최소화 및 이상(Anomaly)현상 방지
- 무결성 향상
- 데이터 구조 안정화
- 정규화는 저장 공간을 감소시키는 방향
- 비정규화(De-normalization)의 주된 목적
- 데이터 접근 성능 향상
- 비정규화는 일부 중복을 허용하여 조회 속도 향상을 목적으로 한다.
- 비정규화(De-normalization)를 고려해야 하는 경우
- 조회 속도를 높여야 할 때
- 비정규화는 데이터 무결성을 일부 희생하고 조회 성능을 높이는 설계 기법
- 정규화 과정에서 “함수적 종속(Functional Dependency)”
- 한 속성의 값이 다른 속성의 값을 결정하는 관계
- 함수적 종속은 X → Y 형태로 표현되며, X가 Y를 결정짓는 관계를 의미
모델링 ✅
- 개념적 모델링
- ‘업무 중심’으로 데이터를 추상화하는 과정
- 엔터티, 속성, 관계를 도출하고 비즈니스 규칙을 정의
- 데이터 모델링의 3단계
- 개념적 → 논리적 → 물리적 순서
- 데이터 모델링은 추상적 수준부터 구체적 수준으로 내려간다.
- 데이터 모델링의 목적
- 데이터 중복을 줄인다
- 업무 규칙을 데이터 구조로 표현한다
- 데이터 무결성을 향상시킨다
- 성능보다는 정확성과 일관성이 핵심이다. 성능은 물리 설계 단계에서 다룬다.
- “업무규칙(Business Rule)”이 모델링에 미치는 영향
- 관계의 존재 여부나 선택성을 결정한다
- 업무규칙은 엔터티 간의 관계, 필수 여부(옵셔널), 참여 제약 등을 정의하는 핵심 근거가 된다
- 논리 모델링 단계에서 주로 수행하는 작업
- 슈퍼타입–서브타입 모델링에서 서브타입 분리 기준
업무 규칙(Business Rule) ✅
- 업무 제약 조건
- 엔터티 발생 조건
- 값의 허용 범위
속성(Attribute) ✅
- 속성(Attribute)의 특징
- 하나의 엔터티는 여러 속성을 가질 수 있다
- 속성은 반드시 하나의 도메인을 가져야 한다
- 속성은 엔터티의 상태나 성질을 나타낸다
- 속성은 엔터티 내부의 구성 요소이며, 다른 엔터티의 속성을 포함하지 않는다.
- 속성의 종류 중 “파생 속성(Derived Attribute)”이란?
- 계산된 값이나 다른 속성으로부터 유도되는 속성
- 다른 속성으로부터 계산되는 값(예: 나이 = 오늘날짜 - 생년월일)
- 속성의 도메인(Domain)
- 속성이 가질 수 있는 값의 범위
- 속성의 값이 될 수 있는 유효한 범위
- 결정자(Determinant)의 정의
기본키 ✅
- 기본키의 조건
- 개체 무결성(Entity Integrity)에 대한 설명
- 기본키는 NULL 값을 가질 수 없다
- 개체 무결성은 기본키 = NULL 불가 + 중복 불가.
- 외래키는 NULL 값을 가질 수 있다.(선택적 관계)
관계형 데이터베이스(RDBMS) ✅
- 관계형 데이터베이스(RDBMS)의 특징
- 데이터의 무결성을 보장
- 릴레이션은 행과 열로 구성
- 릴레이션 간 관계는 외래키로 표현
2과목
실행순서 ✅
DISTINCT
WHERE
GROUP BY
- GROUP BY 사용 조건
- GROUP BY에 나온 컬럼은 SELECT에도 있어야 한다
HAVING
- WHERE 절과 HAVING 절의 차이점
- WHERE은 그룹 전 필터링, HAVING은 그룹 후 필터링
- WHERE은 행 단위 필터링, HAVING은 GROUP BY 이후 집계 결과 필터링
SELECT deptno FROM emp HAVING COUNT() > 5; 틀린 이유
- HAVING은 GROUP BY 없이 단독 사용 불가(집계 함수도 없음).
- HAVING 절이 필요한 이유: 집계 후 조건 필터링
JOIN
- INNER JOIN과 OUTER JOIN의 차이
- INNER JOIN은 양쪽 테이블 모두 매칭되는 행만, OUTER JOIN은 한쪽에 없는 값도 포함
- OUTER JOIN에서 NULL 발생하는 곳: 매칭되지 않는 행이 있는 쪽
- LEFT OUTER JOIN은 왼쪽 기준
- RIGHT OUTER JOIN은 오른쪽 기준
- FULL OUTER JOIN은 둘 다 포함.
- INNER JOIN의 정의
- 조인 조건에 맞는 행만 조회
- INNER JOIN: 조건 일치하는 행만
- LEFT JOIN: 왼쪽 우선
- RIGHT JOIN: 오른쪽 우선
- INNER JOIN
- CROSS JOIN
INDEX
- 인덱스(Index)의 효과(인덱스에 대한 설명)
- 검색 속도 향상
- 데이터 변경(INSERT/UPDATE/DELETE)은 느려질 수 있다.
- 카디널리티가 높을수록 효율적이다
- 모든 컬럼에 인덱스를 만들면
- 저장 공간 증가 / INSERT 성능 저하 -> 즉, 선택적으로 사용
- 인덱스가 효과적인 컬럼
서브쿼리(Subquery)
- 서브쿼리의 특징
- SELECT 절에서 사용 가능
- WHERE 절에서 사용 가능
- FROM 절에서 사용 가능
- FROM 절 서브쿼리는 가상 테이블처럼 사용 가능.
- 서브쿼리(Subquery)의 종류 중 "상관 서브쿼리(Correlated Subquery)"란?
- 서브쿼리 중첩이 가장 깊은 형태
- 상관 서브쿼리는 메인쿼리의 각 행마다 반복적으로 실행되므로 가장 깊은 형태로 간주
- 상관 서브쿼리는 메인쿼리 컬럼을 참조하므로, 메인쿼리 행 수에 따라 반복 실행
- 서브쿼리 결과가 여러 행을 반환할 때 사용해야 하는 연산자
- IN은 여러 값을 비교할 때 사용하며, =은 단일 값 비교만 가능
- 연관 서브쿼리의 특징
- 외부 쿼리의 한 행마다 반복 실행됨
- 연관 서브쿼리 = 외부 쿼리 행마다 실행되는 반복 구조.
연산자
- 집합연산자(UNION, INTERSECT, MINUS)의 특징
- UNION은 중복 제거
- UNION ALL은 중복 허용
- INTERSECT는 교집합
- MINUS는 오름차순 정렬을 반드시 수행하지 않는다(X) = 수행할수도 있음
- 집합연산자는 결과를 기본적으로 정렬하지만, DBMS에 따라 옵티마이저가 정렬을 생략 가능
- BETWEEN 연산자 사용 예시
salary BETWEEN 5000 AND 10000
- BETWEEN은 “A 이상 B 이하” 범위를 의미(작은 값 -> 큰 값)
- ANY와 ALL 연산자의 차이
- ANY는 하나라도 맞으면 TRUE, ALL은 모든 값이 맞아야 TRUE
집계함수
- 집계함수 중 NULL 값을 제외하고 평균을 계산하는 함수
- AVG()는 NULL 값을 자동으로 제외하고 평균을 계산
VIEW
- 뷰(View)에 대한 설명
- 뷰는 하나 이상의 테이블을 기반으로 하는 논리적 가상 테이블
- 뷰는 기본 테이블을 기반으로 생성
- 뷰를 이용해 데이터 접근 권한을 제한 가능
- 뷰는 물리 데이터가 아닌 SQL 결과를 논리적으로 보여주는 객체이며, 일부는 수정 가능
- 단일 테이블 기반 단순 뷰는 수정 가능하지만, 조인·집계 포함 뷰는 일반적으로 수정 불가
- 인라인 뷰(Inline View)의 장점
- SQL 문 안에서만 임시로 뷰처럼 사용 가능하다
- 인라인 뷰는 쿼리 내부에서만 유효한 임시 결과 집합으로, 복잡한 서브쿼리를 단순화하는 데 유용
LIKE
- LIKE 연산자에서 와일드카드
_ 의 의미
- 단일 문자 대체
_ 는 한 글자, % 는 여러 글자를 대체
- LIKE ‘A%’ 의미
EXISTS
- EXISTS 연산자의 특징
- 존재 여부만 검사
- 서브쿼리의 결과가 존재하면 TRUE를 반환한다
- EXISTS는 서브쿼리의 결과 존재 여부를 Boolean으로 반환
DELETE / TRUNCATE
- DELETE와 TRUNCATE의 차이점
- DELETE는 로그 기록, TRUNCATE는 최소 로그 기록
- DELETE는 한 행씩 삭제
- TRUNCATE는 DDL로서 전체 삭제 시 빠르지만,
- 로그가 최소만 남고 WHERE 절을 사용할 수 없다.
트랜잭션 (TRANCTION)
- 트랜잭션(Transaction)의 특성
- ACID(Atomicity, Consistency, Isolation, Durability)
Null
- Oracle에서 NVL(col, 0)의 역할
- NULL 값을 0으로 치환한다
- NVL은 NULL을 특정 값으로 변환하는 함수.
ORDER BY
SELECT dept, COUNT(*) FROM emp WHERE job = 'SALESMAN' GROUP BY dept
HAVING COUNT(*) >= 2 ORDER BY dept;
- 아래 쿼리의 실행 순서
- from
- SQL 논리적 실행 순서는 물리적 순서와 다르며, SELECT는 거의 마지막에 실행
BETWEEN
2과목 SQL
COUNT(*)
SELECT dept, COUNT(*)
FROM emp
GROUP BY dept
HAVING COUNT(*) >= 5;
- 다음 SQL의 실행 결과
- 부서별로 인원 수를 집계하고, 인원이 5명 이상인 부서만 출력
- GROUP BY는 부서별 집계, HAVING은 집계 결과에 조건을 부여

SELECT deptno, COUNT(DISTINCT job)
FROM emp
GROUP BY deptno;
- SQL의 결과
- 부서별로 중복되지 않는 직무(job)의 개수를 출력
- DISTINCT는 중복 제거, COUNT는 개수를 센다.
SELECT job, COUNT(*)
FROM emp
GROUP BY job
UNION
SELECT 'TOTAL', COUNT(*)
FROM emp;
- SQL의 결과
- 각 직무별 인원수와 전체 인원수를 함께 출력
- UNION은 두 SELECT 결과를 합쳐 중복을 제거하며, UNION ALL은 중복 포함.
SELECT COUNT(DISTINCT dept) FROM emp;
SELECT COUNT(*)
FROM emp
WHERE deptno = 10;
서브쿼리
SELECT name, salary
FROM employee
WHERE salary > (SELECT AVG(salary) FROM employee);
- 다음 SQL의 결과
- 평균 급여보다 높은 급여를 받는 직원 목록
- 서브쿼리가 먼저 실행되어 평균 급여를 구하고, 그보다 높은 행만 출력
Null
SELECT NVL(comm, 0) FROM emp;
- NULL 처리 관련 올바른 SQL
- NULL 값을 0으로 대체하여 출력
- Oracle의 NVL, MySQL의 IFNULL, SQL 표준의 COALESCE 함수로 NULL을 대체
GROUP BY
SELECT deptno, SUM(salary)
FROM emp
GROUP BY deptno
ORDER BY SUM(salary) DESC;
- 다음 SQL의 실행 결과
- 부서별 급여 합계를 내림차순으로 정렬한 결과
- GROUP BY로 집계 후, ORDER BY로 정렬.
SELECT deptno, AVG(sal)
FROM emp
GROUP BY deptno
ORDER BY 2 DESC;
SELECT deptno, job, COUNT(*)
FROM emp
GROUP BY ROLLUP(deptno, job);
- SQL의 결과
- 부서별·직무별 집계 + 부서별 소계 + 전체 합계까지 출력
- ROLLUP은 다단계 집계를 수행한다. (GROUPING SETS의 축약형)
SELECT dept, COUNT(*)
FROM emp
GROUP BY dept
HAVING COUNT(*) >= 5;
- GROUP BY + HAVING
- 부서별 직원 수가 5명 이상인 부서를 조회한다
- GROUP BY dept → 부서별 그룹
- HAVING COUNT(*) >= 5 → 집계 조건
- COUNT = 집계함수 -> 집계함수는 WHERE에서 사용 불가
CASE
SELECT name,
CASE WHEN salary >= 5000 THEN 'HIGH'
WHEN salary >= 3000 THEN 'MID'
ELSE 'LOW' END AS grade
FROM emp;
- CASE문을 활용한 올바른 SQL
- 급여 수준에 따라 등급을 분류한 결과
- CASE는 조건 분기문으로, IF-ELSE와 유사하게 작동한다.
RANK
SELECT deptno, job, RANK() OVER(PARTITION BY deptno ORDER BY salary DESC)
FROM emp;
- SQL의 결과를 설명
- 부서별로 급여 순위를 매긴 결과
- 윈도우 함수 RANK()는 PARTITION BY로 그룹을 나누고, ORDER BY로 순위를 매긴다.
SELECT empno, deptno, RANK() OVER(ORDER BY hiredate) AS hire_rank
FROM emp;
- SQL의 결과
- 입사일이 빠를수록 낮은 순위(1부터)로 부여
- RANK()는 순위를 매기되 동점이 있으면 같은 순위, 이후 순위는 건너뛴다.
ROWNUM
SELECT *
FROM emp
WHERE ROWNUM <= 5;
- ROWNUM을 이용해 상위 5개 데이터를 출력하려면
- ROWNUM은 SELECT 출력 순서 기준으로 붙는다.
- 정렬 후 순번을 매기려면 인라인뷰 안에 ORDER BY를 먼저 넣어야 한다.
CUBE
SELECT deptno, job, SUM(salary)
FROM emp
GROUP BY CUBE(deptno, job);
- SQL의 결과
- 부서별, 직무별, 부서+직무별, 전체합계까지 모든 조합의 집계를 수행
- CUBE는 가능한 모든 조합의 그룹핑을 수행하는 다차원 집계 함수