1. 데이터 삽입 (Insert)
새로운 정보를 데이터베이스 레코드에 영구적으로 저장하기 위해 INSERT 명령어를 활용합니다. 특정 열을 지정하거나 모든 열에 대한 값을 제공할 수 있습니다.
1.1 단일 행 및 다중 행 추가
기본적인 문법은 표명과 대입하려는 값 목록을 명시합니다.
-- 특정 필드에 값을 할당하여 단일 사용자 추가
INSERT INTO trainees (trainee_id, full_name, experience_years, group_id)
VALUES (101, '김태호', 5, 1);
-- 한 번의 명령어로 여러 명의 데이터를 동시에 반영
INSERT INTO trainees (trainee_id, full_name, experience_years, group_id)
VALUES
(102, '이민지', 3, 1),
(103, '박성우', 7, 2),
(104, '최지현', 2, 2);
2. 데이터 수정 (Update)
기존에 저장된 레코드의 값을 변경할 때는 UPDATE 문을 사용합니다. 조건문을 생략하면 전체 테이블이 영향을 받으므로 주의가 필요합니다.
2.1 조건 기반 업데이트
특정 인덱스나 이름을 기준으로 정보만 갱신하는 것이 안전합니다.
-- 전 사용자의 경력 연수를 1 년 증가 시키기 (예시용 위험한 쿼리)
-- UPDATE trainees SET experience_years = experience_years + 1;
-- ID 가 101 인 사람의 이름만 변경
UPDATE trainees
SET full_name = '황인환'
WHERE trainee_id = 101;
3. 데이터 삭제 (Delete)
영구적으로 불필요한 데이터를 제거하는 방법으로는 두 가지 주요 옵션이 존재합니다.
3.1 DELETE vs TRUNCATE
- DELETE: 로깅이 발생하며 WHERE 절로 조건부 삭제가 가능하고 트랜잭션 복구가 가능합니다.
- TRUNCATE: DDL 명령어에 가깝고 로그를 최소화하며 속도가 빠릅니다. 조건부가 불가능하여 테이블 전체 초기화입니다.
-- 특정 ID 의 레코드만 제거
DELETE FROM trainees WHERE trainee_id = 102;
-- 테이블 내 모든 데이터를 지우고 자석 재설정 (구조는 유지)
TRUNCATE TABLE trainees;
4. 데이터 조회 (Select Query)
저장된 정보를 검색하고 가공하는 과정입니다. 먼저 연습을 위해 샘플 데이터가 준비되어 있다고 가정합니다.
4.1 필터링 조건 활용
WHERE절을 통해 원하는 데이터만 걸러냅니다. 다양한 비교 연산자와 논리 연자를 결합할 수 있습니다.
- 비교 연산자:
=,!=,>,<,>= - 논리 연산자:
AND,OR,NOT
-- 그룹 ID 가 1 이면서 경력 3 년 이상인 인원 검색
SELECT * FROM trainees
WHERE group_id = 1 AND experience_years >= 3;
-- 이름에 '민' 자가 포함된 경우
SELECT full_name FROM trainees
WHERE full_name LIKE '%민%';
-- 경력이 2 부터 5 사이인 사람
SELECT * FROM trainees
WHERE experience_years BETWEEN 2 AND 5;
-- 특정 ID 목록만 조회
SELECT * FROM trainees
WHERE trainee_id IN (101, 103, 105);
4.2 정렬 및 페이징
조회 결과의 순서를 제어하거나 일부 데이터만 가져옵니다.
-- 경력순으로 오름차점 정렬 후 상위 3 명만 추출
SELECT full_name, experience_years
FROM trainees
ORDER BY experience_years ASC
LIMIT 3;
-- 중복 제거하여 그룹 ID 종류 확인
SELECT DISTINCT group_id FROM trainees;
5. 다중 테이블 연결 (Join)
여러 테이블 간의 관계를 맺고 공통된 키를 이용해 데이터를 통합합니다. 일반적으로 외래키와 주키가 일치해야 합니다.
5.1 내부 연결 (Inner Join)
두 테이블에서 조건을 만족하는 교집합 데이터만 반환합니다.
-- 참여자와 소속 그룹명 합치기
SELECT t.full_name, g.group_name
FROM trainees AS t
INNER JOIN groups AS g ON t.group_id = g.id;
-- 명시적 연결 없이 WHERE 에서 조건 작성 (오래된 방식이지만 동작)
SELECT t.full_name, g.group_name
FROM trainees t, groups g
WHERE t.group_id = g.id;
5.2 외부 연결 (Left / Right Join)
기준 테이블의 모든 데이터를 포함하되 연결된 쪽은 조건을 충족하지 않으면 NULL 로 채웁니다.
-- 코치와 담당 팀 목록 (팀이 없는 코치도 포함)
SELECT c.coach_name, g.group_name
FROM coaches AS c
LEFT JOIN teams AS g ON c.id = g.leader_id;
-- 팀 목록에 매핑되지 않은 코치 찾기
SELECT * FROM coaches c
RIGHT JOIN teams g ON c.id = g.leader_id
WHERE g.leader_id IS NULL;
6. 집계 함수 적용
여러 행의 데이터를 하나의 값으로 요약할 때 GROUP BY와 함께 사용됩니다.
6.1 주요 집계 연산
COUNT(): 행 수 계산SUM(),AVG(): 합계 및 평균MIN(),MAX(): 최소/최대값
-- 각 그룹별 평균 경력 연수
SELECT group_id, AVG(experience_years) as avg_exp
FROM trainees
GROUP BY group_id;
-- 전체 인원수와 최대 경력 값 확인
SELECT COUNT(*), MAX(experience_years)
FROM trainees;
7. 서브쿼리 (Subquery)
하나의 쿼리 안에 또 다른 쿼리를 중첩하여 복잡한 조건을 구현합니다.
7.1 간단한 서브쿼리
외부 쿼리의 WHERE 절이나 FROM 절 내부에 다른 조회 결과를 사용합니다.
-- 특정 코치가 관리하는 그룹에 소속된 직원 찾기
SELECT * FROM trainees
WHERE group_id = (
SELECT id FROM groups
WHERE leader_id = (SELECT id FROM coaches WHERE coach_name='전선생')
);
7.2 존재 여부 확인 (EXISTS)
서브쿼리가 한 줄 이상의 결과를 반환하는지 논리적으로 판단합니다.
-- 해당 코치가 존재하는 경우에만 팀 정보를 표시
SELECT * FROM groups
WHERE EXISTS (
SELECT * FROM coaches WHERE name = '김팀장'
);
7.3 임의/전체 비교 (ANY/ALL)
서브쿼리 결과 집합의 요소들과 개별적으로 비교합니다.
-- 김팀장이 관리하는 그룹 ID 보다 높은 값을 갖는 팀 조회
SELECT * FROM groups
WHERE id >= ANY (SELECT id FROM groups WHERE leader_id = 5);