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;