Skip to main content

3/6/2026

sqld

1. 데이터 모델링

데이터 모델링 특징

특징설명
추상화현실 세계를 일정 형식으로 표현
단순화복잡한 현실을 약속된 규약으로 단순 표현
명확화누구나 이해할 수 있도록 명확하게 표현

데이터 모델링 3단계

단계명칭설명
1단계개념적 데이터 모델링업무 중심의 핵심 엔터티 도출, ERD 작성
2단계논리적 데이터 모델링정규화, 속성·관계 정의, 재사용성 높음
3단계물리적 데이터 모델링DBMS 특성 반영, 실제 테이블 생성

데이터 독립성

구분설명
논리적 독립성개념 스키마 변경이 외부 스키마에 영향을 주지 않음
물리적 독립성내부 스키마 변경이 개념 스키마에 영향을 주지 않음

ERD 표기법 (까마귀발 / IE 표기법)

기호의미
|1 (필수)
O0 (선택)
< (까마귀발)多 (여러 개)

2. 엔터티

엔터티 분류

분류 기준종류설명
유·무형유형 엔터티물리적 형태 존재 (사원, 제품)
유·무형개념 엔터티개념적 존재 (부서, 과목)
유·무형사건 엔터티업무 수행 시 발생 (주문, 청구)
발생 시점기본 엔터티독립적으로 생성 가능
발생 시점중심 엔터티기본 엔터티로부터 발생
발생 시점행위 엔터티두 개 이상의 엔터티 간 행위로 발생

엔터티 명명 규칙

  • 업무에서 사용하는 용어 사용
  • 단수 명사 사용
  • 약어 사용 지양
  • 유일한 이름 부여

3. 속성 (Attribute)

속성 분류

분류종류설명
특성기본 속성업무에서 직접 추출
특성설계 속성설계 과정에서 도출 (일련번호 등)
특성파생 속성다른 속성으로부터 계산·유도 (합계, 평균)
구성단일값 속성한 개의 값만 존재
구성다중값 속성여러 값 존재 → 별도 엔터티 분리 필요

도메인 (Domain)

속성이 가질 수 있는 값의 범위와 데이터 타입, 제약 사항의 집합


4. 관계 (Relationship)

관계 분류

종류설명
존재 관계엔터티 간 존재에 의한 관계 (사원-부서)
행위 관계특정 행위로 인한 관계 (고객-주문)

관계 차수 (Cardinality)

표기의미
1:1일대일
1:M일대다
M:N다대다 → 실제 구현 시 교차 엔터티로 분리

관계 선택성

구분설명
필수 참여반드시 관계가 존재해야 함
선택 참여관계가 없어도 됨

5. 식별자 (Identifier)

주식별자 특성

특성설명
유일성인스턴스를 유일하게 구별
최소성최소한의 속성으로 구성
불변성값이 변하지 않아야 함
존재성NULL 불가

식별자 분류

분류 기준종류설명
대표성주식별자엔터티를 대표하는 식별자
대표성보조 식별자주식별자 외 유일성 보장
스스로내부 식별자엔터티 내에서 스스로 생성
스스로외부 식별자타 엔터티로부터 상속 (FK)
속성 수단일 식별자하나의 속성으로 구성
속성 수복합 식별자두 개 이상의 속성으로 구성
대체 여부본질 식별자업무에 의해 만들어진 식별자
대체 여부인조 식별자인위적으로 만든 식별자 (시퀀스)

식별 관계 vs 비식별 관계

구분식별 관계비식별 관계
FK 위치자식의 PK에 포함자식의 일반 속성
부모 존재부모 필수부모 없어도 존재 가능
실선/점선실선점선

5-1. 키(Key)의 종류

키 개념 분류

키 종류설명특징
슈퍼키 (Super Key)행을 유일하게 식별할 수 있는 속성의 집합유일성 O, 최소성 X
후보키 (Candidate Key)슈퍼키 중 최소 속성으로 구성된 키유일성 O, 최소성 O
기본키 (Primary Key)후보키 중 대표로 선택된 키NULL 불가, 중복 불가
대리키 (Surrogate Key)기본키 대신 인위적으로 생성한 키시퀀스·일련번호
대체키 (Alternate Key)후보키 중 기본키가 되지 못한 나머지 키UNIQUE 제약
외래키 (Foreign Key)다른 테이블의 기본키를 참조하는 키참조 무결성 보장
복합키 (Composite Key)두 개 이상의 속성으로 구성된 키-

키 간의 관계

슈퍼키
└── 후보키 (최소성 추가)
├── 기본키 (대표 선택, NOT NULL)
│ └── 대리키 (기본키 대체 목적)
└── 대체키 (선택받지 못한 후보키)

무결성 제약조건

종류설명
개체 무결성기본키는 NULL 불가, 중복 불가
참조 무결성외래키는 참조 대상 PK에 존재하는 값이거나 NULL 이어야 함
도메인 무결성속성 값은 정의된 도메인 범위 내에 있어야 함
NULL 무결성NOT NULL로 지정된 속성에 NULL 불가
유일 무결성UNIQUE로 지정된 속성은 중복 불가

6. 정규화 (Normalization)

이상 현상 (Anomaly)

종류설명
삽입 이상불필요한 데이터를 함께 삽입해야 하는 경우
삭제 이상원하지 않는 데이터까지 삭제되는 경우
갱신 이상일부만 갱신되어 데이터 불일치 발생

정규화 단계

단계명칭제거 대상
1NF제1정규형반복 그룹 제거, 원자값으로 구성
2NF제2정규형부분 함수 종속 제거 (복합 PK일 때)
3NF제3정규형이행 함수 종속 제거 (A→B→C)
BCNF보이스-코드 정규형결정자가 후보키가 아닌 함수 종속 제거
4NF제4정규형다치 종속 제거
5NF제5정규형조인 종속 제거

반정규화 (De-normalization)

기법설명
테이블 병합1:1 또는 1:M 관계 테이블 합침
테이블 분할수평/수직 분할
중복 컬럼 추가조인 비용 줄이기 위해 속성 중복
파생 컬럼 추가집계값을 컬럼으로 저장

7. 관계형 데이터 모델

관계형 데이터베이스 용어

관계형 용어파일 시스템 용어설명
릴레이션 (Relation)파일테이블
튜플 (Tuple)레코드행 (Row)
속성 (Attribute)필드열 (Column)
도메인 (Domain)-속성 값의 범위
카디널리티레코드 수행의 수
차수필드 수열의 수

관계 대수 연산자

연산자기호설명
셀렉션σ조건에 맞는 튜플 추출 (행 선택)
프로젝션π특정 속성만 추출 (열 선택)
조인두 릴레이션을 공통 속성으로 결합
합집합두 릴레이션의 합
교집합두 릴레이션의 교
차집합-한쪽에만 있는 튜플
카티션 프로덕트×모든 튜플의 조합
디비전÷나눗셈 연산

8. 성능 데이터 모델링

인덱스 (Index)

항목내용
목적검색 속도 향상
B-Tree 구조일반적 인덱스 구조, 범위 검색 유리
인덱스 손익 분기전체 데이터의 약 10~15% 이하 조회 시 유리
인덱스 컬럼 순서= 조건 → 범위 조건 순서로 구성

분산 데이터베이스 투명성

종류설명
위치 투명성데이터 저장 위치를 몰라도 접근 가능
복제 투명성복제 여부를 몰라도 접근 가능
분할 투명성분할 여부를 몰라도 접근 가능
병행 투명성다수 트랜잭션 동시 수행 시 결과 보장
장애 투명성장애 발생 시 자동 복구

SQL 문법

SQL 명령어 분류 (DDL / DML / TCL / DCL)

분류명령어설명AUTO COMMIT
DDLCREATE객체 생성O (자동)
DDLALTER객체 구조 변경O (자동)
DDLDROP객체 삭제O (자동)
DDLTRUNCATE테이블 전체 행 삭제 (롤백 불가)O (자동)
DDLRENAME객체 이름 변경O (자동)
DMLSELECT데이터 조회X
DMLINSERT데이터 삽입X
DMLUPDATE데이터 수정X
DMLDELETE데이터 삭제 (롤백 가능)X
TCLCOMMIT트랜잭션 확정-
TCLROLLBACK트랜잭션 취소-
TCLSAVEPOINT중간 저장점 설정-
DCLGRANT권한 부여-
DCLREVOKE권한 회수-

TRUNCATE vs DELETE: TRUNCATE는 DDL이므로 롤백 불가, DELETE는 DML이므로 롤백 가능 DDL은 자동 커밋, DML은 수동 커밋


SELECT 쿼리 실행 순서

SELECT   col          -- 5. 열 선택 및 표현식 계산
FROM table -- 1. 테이블 접근
WHERE condition -- 2. 행 필터링
GROUP BY col -- 3. 그룹화
HAVING condition -- 4. 그룹 필터링
ORDER BY col -- 6. 정렬
LIMIT n -- 7. 행 수 제한
실행 순서설명
1FROM참조 테이블 결정
2WHERE개별 행 조건 필터
3GROUP BY그룹 집계
4HAVING그룹 조건 필터
5SELECT출력 컬럼 결정
6ORDER BY정렬 (SELECT 별칭 사용 가능)
7LIMIT / FETCH행 수 제한

WHERE에서는 SELECT 별칭(alias) 사용 불가 - SELECT보다 먼저 실행되기 때문


Alias (별칭)

-- 컬럼 별칭
SELECT salary * 12 AS annual_salary
FROM employees;

-- 공백/특수문자 포함 시 큰따옴표 사용
SELECT salary * 12 AS "연봉 합계"
FROM employees;

-- 테이블 별칭
SELECT e.name, d.dept_name
FROM employees e, departments d
WHERE e.dept_id = d.id;
규칙내용
AS 생략가능 (col "별칭")
큰따옴표공백·특수문자·대소문자 구분 시 필수
WHERE 사용불가 (실행 순서상 SELECT 이후)
ORDER BY 사용가능
HAVING 사용불가

식별자 구분

SQL에서 식별자(Identifier)는 테이블명·컬럼명·별칭 등 객체 이름을 가리키며, 리터럴(문자열 값)과 구분해서 사용해야 함

따옴표 종류

기호종류용도예시
' (작은따옴표)문자열 리터럴값 비교, 문자열 데이터WHERE name = '홍길동'
" (큰따옴표)인용 식별자컬럼명·테이블명·별칭에 사용SELECT sal AS "연봉 합계"
` (백틱, MySQL)인용 식별자MySQL에서 컬럼명·테이블명SELECT `order` FROM t

Oracle/표준 SQL은 큰따옴표, MySQL은 백틱을 식별자 인용에 사용

일반 식별자 vs 인용 식별자

구분일반 식별자인용 식별자
표기따옴표 없음큰따옴표로 감쌈
대소문자구분 안 함 (내부적으로 대문자로 처리)작성한 대로 구분
예약어 사용불가가능 ("SELECT", "FROM")
공백·특수문자불가가능 ("연봉 합계")
시작 문자문자 또는 _제한 없음
-- 일반 식별자: 대소문자 무시
SELECT EmpName FROM Employees; -- empname, EMPNAME 모두 동일

-- 인용 식별자: 대소문자 구분, 공백/예약어 허용
SELECT "EmpName", "연봉 합계" FROM "My Table";

-- 예약어를 컬럼명으로 쓸 경우 큰따옴표 필수
CREATE TABLE t ("select" NUMBER, "from" VARCHAR2(10));

식별자 명명 규칙

규칙내용
시작 문자반드시 문자(알파벳) 또는 _ 로 시작
사용 가능 문자문자, 숫자, _, $, #
최대 길이Oracle 30자, SQL Server 128자
예약어일반 식별자로 사용 불가 (인용 식별자는 가능)
중복동일 스코프 내 중복 불가

NULL 특징

특징설명
NULL의 정의알 수 없는 값, 부재 값 (0이나 공백과 다름)
산술 연산NULL 포함 연산 결과는 항상 NULL
비교 연산NULL = NULL → FALSE (비교 불가)
NULL 비교IS NULL / IS NOT NULL 사용
집계 함수COUNT(*) 제외, NULL 행은 집계에서 제외
정렬Oracle: NULL 가장 크게 취급 / SQL Server: 가장 작게 취급
-- NULL 처리 함수
NVL(col, 0) -- Oracle: NULL이면 0으로 대체
ISNULL(col, 0) -- SQL Server
COALESCE(col1, col2, 0) -- 표준 SQL: 첫 번째 비-NULL 반환
NULLIF(col, 0) -- col이 0이면 NULL 반환

-- NULL 비교
WHERE col IS NULL
WHERE col IS NOT NULL

-- NULL 포함 연산 예시
SELECT 1 + NULL; -- NULL
SELECT NULL = NULL; -- NULL (FALSE가 아님)

데이터 타입

분류타입설명
문자CHAR(n)고정 길이, 남은 자리 공백 패딩
문자VARCHAR2(n) / VARCHAR(n)가변 길이, 실제 길이만 저장
문자CLOB대용량 문자 데이터
숫자NUMBER(p, s)전체 자릿수 p, 소수점 이하 s
숫자INT / INTEGER정수
날짜DATE날짜+시간 (Oracle: 년월일시분초)
날짜TIMESTAMPDATE보다 정밀한 시간 (나노초)
이진BLOB대용량 이진 데이터

CHAR vs VARCHAR: CHAR('A') = CHAR('A ') 비교 시 공백 무시하여 같음, VARCHAR는 공백 포함하여 다름


WHERE 조건 연산자

연산자설명예시
=같음WHERE age = 30
<> / !=다름WHERE age <> 30
BETWEEN A AND BA 이상 B 이하 (경계 포함)WHERE age BETWEEN 20 AND 30
IN (list)목록 중 하나WHERE dept IN ('HR', 'IT')
LIKE패턴 매칭WHERE name LIKE '김%'
IS NULLNULL 여부WHERE col IS NULL
NOT부정WHERE NOT age = 30
-- LIKE 와일드카드
% -- 0개 이상 임의 문자
_ -- 정확히 1개 임의 문자

WHERE name LIKE '김%' -- 김으로 시작
WHERE name LIKE '%수' -- 수로 끝남
WHERE name LIKE '_수_' -- 3글자 중간이 수
WHERE name LIKE '\_홍%' ESCAPE '\' -- _ 문자 자체를 검색

JOIN

종류설명
INNER JOIN양쪽 모두 일치하는 행만 반환
LEFT OUTER JOIN왼쪽 전체 + 오른쪽 일치 (없으면 NULL)
RIGHT OUTER JOIN오른쪽 전체 + 왼쪽 일치 (없으면 NULL)
FULL OUTER JOIN양쪽 전체 (일치 없으면 NULL)
CROSS JOIN카티션 곱 (모든 조합)
SELF JOIN같은 테이블끼리 조인
NATURAL JOIN동일 컬럼명 자동 조인 (ON/USING 불필요)
-- ANSI 표준 JOIN
SELECT e.name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.id;

-- OUTER JOIN
SELECT e.name, d.dept_name
FROM employees e
LEFT OUTER JOIN departments d ON e.dept_id = d.id;

-- Oracle 구문 (+): 오른쪽 테이블이 기준
WHERE e.dept_id = d.id(+) -- LEFT OUTER JOIN 과 동일

집합 연산자

연산자중복 제거설명
UNIONO합집합 (중복 제거)
UNION ALLX합집합 (중복 포함)
INTERSECTO교집합
MINUS / EXCEPTO차집합

조건: 양쪽 SELECT의 컬럼 수와 데이터 타입이 동일해야 함

SELECT name FROM employees
UNION
SELECT name FROM contractors;

단일행 함수

문자 함수

함수설명예시
UPPER(s)대문자 변환UPPER('hello')HELLO
LOWER(s)소문자 변환LOWER('HELLO')hello
SUBSTR(s, n, len)부분 문자열SUBSTR('HELLO', 2, 3)ELL
LENGTH(s)문자열 길이LENGTH('ABC')3
TRIM(s)앞뒤 공백 제거TRIM(' AB ')AB
LPAD(s, n, c)왼쪽 패딩LPAD('5', 3, '0')005
RPAD(s, n, c)오른쪽 패딩RPAD('5', 3, '0')500
REPLACE(s, a, b)치환REPLACE('ABC', 'B', 'X')AXC
INSTR(s, c)위치 반환INSTR('ABC', 'B')2
CONCAT(a, b)문자열 연결CONCAT('AB', 'CD')ABCD

숫자 함수

함수설명예시
ROUND(n, d)반올림ROUND(3.567, 2)3.57
TRUNC(n, d)버림TRUNC(3.567, 2)3.56
CEIL(n)올림CEIL(3.1)4
FLOOR(n)내림FLOOR(3.9)3
MOD(a, b)나머지MOD(10, 3)1
ABS(n)절대값ABS(-5)5
SIGN(n)부호 반환SIGN(-3)-1
POWER(a, b)거듭제곱POWER(2, 3)8

날짜 함수

함수설명
SYSDATE현재 날짜+시간 (Oracle)
GETDATE()현재 날짜+시간 (SQL Server)
CURRENT_DATE현재 날짜 (표준)
ADD_MONTHS(d, n)n개월 더하기
MONTHS_BETWEEN(d1, d2)두 날짜의 개월 차
LAST_DAY(d)해당 월의 마지막 날
NEXT_DAY(d, '요일')다음 지정 요일 날짜
TO_DATE(s, fmt)문자열 → 날짜 변환
TO_CHAR(d, fmt)날짜 → 문자열 변환
-- 날짜 연산
SELECT SYSDATE + 7 FROM dual; -- 7일 후
SELECT SYSDATE - 1 FROM dual; -- 어제
SELECT MONTHS_BETWEEN(SYSDATE, hire_date) -- 근무 개월 수
FROM employees;

변환 함수

함수설명
TO_CHAR(n/d, fmt)숫자·날짜 → 문자
TO_NUMBER(s, fmt)문자 → 숫자
TO_DATE(s, fmt)문자 → 날짜
CAST(expr AS type)표준 타입 변환

조건 함수

-- CASE WHEN
SELECT name,
CASE grade
WHEN 'A' THEN '우수'
WHEN 'B' THEN '보통'
ELSE '미흡'
END AS grade_label
FROM students;

-- DECODE (Oracle)
SELECT DECODE(grade, 'A', '우수', 'B', '보통', '미흡')
FROM students;

-- CASE WHEN 범위 조건
SELECT name,
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
ELSE 'C'
END AS grade
FROM students;

집계 함수 (그룹 함수)

함수설명NULL 처리
COUNT(*)전체 행 수NULL 포함
COUNT(col)해당 컬럼 행 수NULL 제외
SUM(col)합계NULL 제외
AVG(col)평균NULL 제외
MAX(col)최대값NULL 제외
MIN(col)최소값NULL 제외
STDDEV(col)표준편차NULL 제외
VARIANCE(col)분산NULL 제외
-- GROUP BY / HAVING
SELECT dept_id, COUNT(*), AVG(salary)
FROM employees
GROUP BY dept_id
HAVING AVG(salary) > 5000
ORDER BY dept_id;

WHERE vs HAVING: WHERE는 개별 행 필터(집계 함수 불가), HAVING은 그룹 필터(집계 함수 사용 가능)


서브쿼리 (Subquery)

종류위치설명
단일행 서브쿼리WHERE결과가 1행 1열, = < > 사용
다중행 서브쿼리WHERE결과가 여러 행, IN ANY ALL 사용
다중열 서브쿼리WHERE결과가 여러 열
인라인 뷰FROMFROM 절의 서브쿼리, 임시 테이블처럼 사용
스칼라 서브쿼리SELECTSELECT 절의 서브쿼리, 단일값 반환
상관 서브쿼리WHERE외부 쿼리 참조, 행마다 실행
-- 다중행 서브쿼리
SELECT name FROM employees
WHERE dept_id IN (SELECT id FROM departments WHERE location = 'Seoul');

-- ANY / ALL
WHERE salary > ANY (SELECT salary FROM employees WHERE grade = 'B') -- B 중 하나라도 크면
WHERE salary > ALL (SELECT salary FROM employees WHERE grade = 'B') -- B 전부보다 크면

-- 인라인 뷰
SELECT name, salary
FROM (SELECT name, salary, RANK() OVER (ORDER BY salary DESC) AS rnk FROM employees) t
WHERE rnk <= 3;

-- 스칼라 서브쿼리
SELECT name, (SELECT dept_name FROM departments WHERE id = e.dept_id) AS dept
FROM employees e;

윈도우 함수 (분석 함수)

분류함수설명RANK/ROW_NUMBER 차이
순위ROW_NUMBER()고유 순위 - 동일값도 항상 다른 번호1, 2, 3, 4
순위RANK()동일값 동순위, 다음 순위 건너뜀1, 1, 3, 4
순위DENSE_RANK()동일값 동순위, 건너뜀 없음1, 1, 2, 3
분포NTILE(n)전체 행을 n개 그룹으로 균등 분할-
분포PERCENT_RANK()순위 백분율 (0~1)-
분포CUME_DIST()누적 분포 비율-
행 참조LAG(col, n, default)현재 행 기준 이전 n번째 행 값-
행 참조LEAD(col, n, default)현재 행 기준 이후 n번째 행 값-
행 참조FIRST_VALUE(col)파티션 내 첫 번째 행 값-
행 참조LAST_VALUE(col)파티션 내 마지막 행 값 (RANGE 주의)-
집계SUM(col) OVER()파티션 내 누적 합-
집계AVG(col) OVER()파티션 내 평균-
집계COUNT(col) OVER()파티션 내 건수-

RANK vs DENSE_RANK vs ROW_NUMBER: 동점자 처리가 핵심 차이. RANK는 다음 순위를 건너뛰고, DENSE_RANK는 연속, ROW_NUMBER는 항상 고유

-- 기본 구조: 함수() OVER (PARTITION BY ... ORDER BY ...)
SELECT name, dept_id, salary,
ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS row_num,
RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rnk,
DENSE_RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS dense_rnk,
LAG(salary, 1, 0) OVER (ORDER BY hire_date) AS prev_salary,
LEAD(salary, 1, 0) OVER (ORDER BY hire_date) AS next_salary,
SUM(salary) OVER (PARTITION BY dept_id) AS dept_total
FROM employees;

-- 같은 salary가 100, 100, 90 일 때 각 함수 결과:
-- ROW_NUMBER: 1, 2, 3
-- RANK: 1, 1, 3
-- DENSE_RANK: 1, 1, 2

ROLLUP / CUBE / GROUPING SETS

구문생성되는 그룹 조합설명
GROUP BY a, b(a, b)일반 그룹화, 소계 없음
ROLLUP(a, b)(a, b) → (a) → ()계층적 소계, 오른쪽부터 제거
CUBE(a, b)(a, b), (a), (b), ()모든 조합 소계
GROUPING SETS(a, b)(a), (b)지정한 그룹만 개별 소계
GROUPING(col)-소계 행이면 1, 일반 행이면 0 반환
SELECT dept_id, job, SUM(salary)
FROM employees
GROUP BY ROLLUP(dept_id, job);

ROLLUP 실행 전 (원본 데이터)

 dept_id | job   | salary
---------+-------+--------
10 | DEV | 5000
10 | DEV | 4000
10 | QA | 3000
20 | MGR | 7000

ROLLUP 실행 후 (결과)

 dept_id | job   | SUM(salary)  -- 의미
---------+-------+-------------
10 | DEV | 9000 -- (dept=10, job=DEV) 소계
10 | QA | 3000 -- (dept=10, job=QA) 소계
10 | NULL | 12000 -- (dept=10) 소계 ← ROLLUP 생성
20 | MGR | 7000 -- (dept=20, job=MGR) 소계
20 | NULL | 7000 -- (dept=20) 소계 ← ROLLUP 생성
NULL | NULL | 19000 -- 전체 합계 ← ROLLUP 생성

GROUPING(dept_id) = 1 이면 소계 행, = 0 이면 일반 행임을 구분할 수 있음

-- CUBE: 모든 조합
SELECT dept_id, job, SUM(salary)
FROM employees
GROUP BY CUBE(dept_id, job);
-- 결과: (dept, job), (dept), (job), (전체) 4가지 조합 모두 생성

-- GROUPING SETS: 원하는 조합만
SELECT dept_id, job, SUM(salary)
FROM employees
GROUP BY GROUPING SETS((dept_id), (job));
-- 결과: dept 소계 + job 소계만 생성 (전체 합계 미포함)

-- GROUPING() 활용
SELECT
CASE GROUPING(dept_id) WHEN 1 THEN '전체' ELSE TO_CHAR(dept_id) END AS dept,
SUM(salary)
FROM employees
GROUP BY ROLLUP(dept_id);

PIVOT / UNPIVOT

행(Row)을 열(Column)로, 또는 열을 행으로 변환하는 구문

구문방향설명
PIVOT행 → 열특정 컬럼 값을 새로운 컬럼으로 전환
UNPIVOT열 → 행컬럼을 행으로 풀어서 정규화

PIVOT 전 (원본)

 year | quarter | sales
------+---------+-------
2024 | Q1 | 100
2024 | Q2 | 200
2024 | Q3 | 150
2024 | Q4 | 300

PIVOT 후

 year |  Q1  |  Q2  |  Q3  |  Q4
------+------+------+------+------
2024 | 100 | 200 | 150 | 300
-- Oracle PIVOT
SELECT *
FROM (
SELECT year, quarter, sales FROM quarterly_sales
)
PIVOT (
SUM(sales) -- 집계 함수
FOR quarter IN ('Q1', 'Q2', 'Q3', 'Q4') -- 열로 만들 값
);

-- Oracle UNPIVOT
SELECT year, quarter, sales
FROM pivot_result
UNPIVOT (
sales -- 값을 담을 컬럼명
FOR quarter IN (Q1, Q2, Q3, Q4) -- 열 → 행으로 풀 컬럼들
);

-- CASE WHEN으로 동일 효과 (표준 SQL)
SELECT year,
SUM(CASE WHEN quarter = 'Q1' THEN sales END) AS Q1,
SUM(CASE WHEN quarter = 'Q2' THEN sales END) AS Q2,
SUM(CASE WHEN quarter = 'Q3' THEN sales END) AS Q3,
SUM(CASE WHEN quarter = 'Q4' THEN sales END) AS Q4
FROM quarterly_sales
GROUP BY year;

DCL / TCL 상세

-- 권한 부여/회수
GRANT SELECT, INSERT ON employees TO user1;
REVOKE INSERT ON employees FROM user1;

-- WITH GRANT OPTION: 권한 받은 사용자가 다른 사용자에게 재부여 가능
GRANT SELECT ON employees TO user1 WITH GRANT OPTION;

-- 트랜잭션
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
SAVEPOINT sp1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
ROLLBACK TO sp1; -- sp1 이후 작업만 취소
COMMIT;

트랜잭션 특성 (ACID)

특성영문설명
원자성Atomicity전부 성공하거나 전부 실패
일관성Consistency트랜잭션 전후 데이터 무결성 유지
격리성Isolation다른 트랜잭션 간섭 없음
지속성DurabilityCOMMIT 후 영구 반영

DDL 구문 상세

-- 테이블 생성
CREATE TABLE employees (
id NUMBER(10) PRIMARY KEY,
name VARCHAR2(50) NOT NULL,
dept_id NUMBER(10) REFERENCES departments(id),
salary NUMBER(10, 2) DEFAULT 0,
hire_date DATE
);

-- 컬럼 추가
ALTER TABLE employees ADD phone VARCHAR2(20);

-- 컬럼 수정
ALTER TABLE employees MODIFY phone VARCHAR2(30);

-- 컬럼 삭제
ALTER TABLE employees DROP COLUMN phone;

-- 테이블 삭제
DROP TABLE employees;
DROP TABLE employees CASCADE CONSTRAINTS; -- 참조 제약조건도 함께 제거

-- 전체 데이터 삭제 (롤백 불가)
TRUNCATE TABLE employees;

제약조건 (Constraint)

제약조건키워드NULL 허용중복 허용설명
기본키PRIMARY KEYXXNOT NULL + UNIQUE 조합, 테이블당 1개
외래키FOREIGN KEYOO참조 대상 PK/UK 값이거나 NULL
유일UNIQUEOXNULL은 중복 허용 (DBMS마다 상이)
NOT NULLNOT NULLXONULL 불가
체크CHECK--지정 조건 만족해야 함
기본값DEFAULT--값 미입력 시 기본값 사용

외래키 참조 동작 (ON DELETE / ON UPDATE)

옵션설명
CASCADE부모 행 삭제/수정 시 자식 행도 함께 삭제/수정
SET NULL부모 행 삭제/수정 시 자식 FK 컬럼을 NULL로 변경
SET DEFAULT부모 행 삭제/수정 시 자식 FK 컬럼에 기본값 설정
RESTRICT자식 행이 존재하면 부모 행 삭제/수정 불가
NO ACTIONRESTRICT와 유사, 트랜잭션 종료 시 검사
-- 제약조건 컬럼 레벨
CREATE TABLE orders (
order_id NUMBER PRIMARY KEY,
cust_id NUMBER NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
amount NUMBER CHECK (amount > 0),
status VARCHAR2(10) DEFAULT 'PENDING'
);

-- 제약조건 테이블 레벨 (이름 부여)
CREATE TABLE orders (
order_id NUMBER,
cust_id NUMBER,
CONSTRAINT pk_order PRIMARY KEY (order_id),
CONSTRAINT fk_order_cust FOREIGN KEY (cust_id)
REFERENCES customers(id) ON DELETE SET NULL
);

-- 제약조건 추가/삭제
ALTER TABLE employees ADD CONSTRAINT emp_dept_fk
FOREIGN KEY (dept_id) REFERENCES departments(id) ON DELETE CASCADE;

ALTER TABLE employees DROP CONSTRAINT emp_dept_fk;

-- 제약조건 비활성화/활성화 (Oracle)
ALTER TABLE employees DISABLE CONSTRAINT emp_dept_fk;
ALTER TABLE employees ENABLE CONSTRAINT emp_dept_fk;