
1. INSERT - 데이터 삽입
기본 문법
INSERT INTO 테이블명 (컬럼1, 컬럼2, 컬럼3, ...)
VALUES (값1, 값2, 값3, ...);

예제 1: 모든 컬럼에 데이터 삽입
-- users 테이블에 새로운 사용자 추가
INSERT INTO users (id, name, email, age, created_at)
VALUES (1, '김철수', 'kim@example.com', 25, '2024-01-15');
예제 2: 일부 컬럼만 지정
-- 특정 컬럼만 지정 (나머지는 기본값 또는 NULL)
INSERT INTO users (name, email)
VALUES ('이영희', 'lee@example.com');
예제 3: 여러 행 한 번에 삽입
INSERT INTO users (name, email, age)
VALUES
('박민수', 'park@example.com', 30),
('정수진', 'jung@example.com', 28),
('최동욱', 'choi@example.com', 35);
예제 4: SELECT 결과를 삽입
-- 다른 테이블의 데이터를 조회하여 삽입
INSERT INTO users_backup (name, email, age)
SELECT name, email, age
FROM users
WHERE age > 30;
예제 5: 기본값 사용
-- DEFAULT 키워드로 기본값 사용
INSERT INTO products (product_name, price, stock)
VALUES ('노트북', 1500000, DEFAULT);
2. UPDATE - 데이터 수정
기본 문법
UPDATE 테이블명
SET 컬럼1 = 값1, 컬럼2 = 값2, ...
WHERE 조건;
⚠️ 주의: WHERE 절을 빠뜨리면 모든 행이 수정됩니다!

예제 1: 단일 컬럼 수정
-- 특정 사용자의 이메일 변경
UPDATE users
SET email = 'newemail@example.com'
WHERE id = 1;
예제 2: 여러 컬럼 동시 수정
-- 여러 정보를 한 번에 수정
UPDATE users
SET email = 'update@example.com',
age = 26,
updated_at = NOW()
WHERE name = '김철수';
예제 3: 조건에 맞는 여러 행 수정
-- 30세 이상 모든 사용자의 등급 상향
UPDATE users
SET membership_level = 'GOLD'
WHERE age >= 30;
예제 4: 계산식으로 수정
-- 모든 제품 가격 10% 인상
UPDATE products
SET price = price * 1.1;
-- 재고 5개 감소
UPDATE products
SET stock = stock - 5
WHERE product_id = 101;
예제 5: 서브쿼리를 이용한 수정
-- 평균 나이보다 많은 사용자의 상태 변경
UPDATE users
SET status = 'SENIOR'
WHERE age > (SELECT AVG(age) FROM users);
예제 6: CASE 문을 이용한 조건부 수정
-- 나이대별로 다른 등급 부여
UPDATE users
SET grade = CASE
WHEN age < 20 THEN 'TEEN'
WHEN age BETWEEN 20 AND 30 THEN 'YOUNG'
WHEN age BETWEEN 31 AND 50 THEN 'ADULT'
ELSE 'SENIOR'
END;
3. DELETE - 데이터 삭제
기본 문법
DELETE FROM 테이블명
WHERE 조건;
⚠️ 주의: WHERE 절을 빠뜨리면 모든 데이터가 삭제됩니다!

예제 1: 특정 행 삭제
-- ID가 1인 사용자 삭제
DELETE FROM users
WHERE id = 1;
예제 2: 조건에 맞는 여러 행 삭제
-- 30세 미만 사용자 모두 삭제
DELETE FROM users
WHERE age < 30;
-- 비활성 계정 삭제
DELETE FROM users
WHERE status = 'INACTIVE' AND last_login < '2023-01-01';
예제 3: 서브쿼리를 이용한 삭제
-- 주문 내역이 없는 사용자 삭제
DELETE FROM users
WHERE id NOT IN (SELECT DISTINCT user_id FROM orders);
예제 4: JOIN을 이용한 삭제 (MySQL)
-- 주문이 없는 제품 삭제
DELETE p
FROM products p
LEFT JOIN orders o ON p.product_id = o.product_id
WHERE o.product_id IS NULL;
예제 5: 모든 데이터 삭제
-- 모든 행 삭제 (구조는 유지)
DELETE FROM users;
-- 또는 TRUNCATE 사용 (더 빠름, AUTO_INCREMENT 초기화)
TRUNCATE TABLE users;
4. 실전 활용 예제
시나리오 1: 회원가입 처리
-- 신규 회원 등록
INSERT INTO users (name, email, password, created_at)
VALUES ('홍길동', 'hong@example.com', 'hashed_password', NOW());
-- 가입 축하 포인트 지급
UPDATE users
SET points = 1000
WHERE email = 'hong@example.com';
시나리오 2: 주문 처리
-- 주문 생성
INSERT INTO orders (user_id, product_id, quantity, order_date)
VALUES (5, 101, 2, NOW());
-- 재고 차감
UPDATE products
SET stock = stock - 2
WHERE product_id = 101;
시나리오 3: 데이터 정리
-- 1년 이상 로그인하지 않은 사용자 삭제
DELETE FROM users
WHERE last_login < DATE_SUB(NOW(), INTERVAL 1 YEAR);
-- 관련 데이터도 함께 삭제 (외래키 ON DELETE CASCADE가 없는 경우)
DELETE FROM user_logs WHERE user_id IN (
SELECT id FROM users WHERE last_login < DATE_SUB(NOW(), INTERVAL 1 YEAR)
);
시나리오 4: 대량 데이터 처리
-- 대량 삽입 (성능 최적화)
INSERT INTO logs (user_id, action, created_at)
VALUES
(1, 'login', NOW()),
(2, 'purchase', NOW()),
(3, 'logout', NOW()),
(1, 'view', NOW()),
(2, 'search', NOW());
-- 조건부 대량 업데이트
UPDATE products
SET discount_rate = CASE
WHEN category = 'ELECTRONICS' THEN 0.15
WHEN category = 'CLOTHING' THEN 0.20
WHEN category = 'BOOKS' THEN 0.10
ELSE 0.05
END
WHERE sale_event = TRUE;
5. 중요 개념 및 주의사항
트랜잭션 사용
-- 여러 작업을 하나의 단위로 처리
START TRANSACTION;
UPDATE accounts SET balance = balance - 10000 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 10000 WHERE user_id = 2;
COMMIT; -- 성공 시 저장
-- ROLLBACK; -- 실패 시 취소
WHERE 절 없이 실행 방지
-- 안전 모드 활성화 (MySQL Workbench)
SET SQL_SAFE_UPDATES = 1;
-- 이제 WHERE 없는 UPDATE/DELETE는 오류 발생
UPDATE users SET age = 30; -- 오류!
조건 확인 후 실행
-- 먼저 SELECT로 확인
SELECT * FROM users WHERE age < 20;
-- 확인 후 삭제
DELETE FROM users WHERE age < 20;
AUTO_INCREMENT 처리
-- INSERT 시 자동 증가 컬럼은 생략
INSERT INTO users (name, email) -- id는 자동 생성
VALUES ('테스트', 'test@example.com');
-- 마지막 삽입된 ID 확인
SELECT LAST_INSERT_ID();
6. 데이터베이스별 차이점
MySQL
-- 중복 시 무시
INSERT IGNORE INTO users (id, name) VALUES (1, '홍길동');
-- 중복 시 업데이트
INSERT INTO users (id, name, email)
VALUES (1, '홍길동', 'hong@example.com')
ON DUPLICATE KEY UPDATE email = 'hong@example.com';
-- LIMIT 사용 가능
DELETE FROM users WHERE age < 20 LIMIT 10;
PostgreSQL
-- RETURNING으로 삽입된 데이터 반환
INSERT INTO users (name, email)
VALUES ('홍길동', 'hong@example.com')
RETURNING id, created_at;
-- UPSERT (충돌 시 업데이트)
INSERT INTO users (id, name, email)
VALUES (1, '홍길동', 'hong@example.com')
ON CONFLICT (id)
DO UPDATE SET email = EXCLUDED.email;
SQL Server
-- OUTPUT으로 변경된 데이터 확인
DELETE FROM users
OUTPUT DELETED.*
WHERE age < 20;
-- MERGE 문 (INSERT + UPDATE + DELETE)
MERGE INTO target_table AS target
USING source_table AS source
ON target.id = source.id
WHEN MATCHED THEN UPDATE SET target.name = source.name
WHEN NOT MATCHED THEN INSERT (id, name) VALUES (source.id, source.name);
7. 성능 최적화 팁
1. 인덱스 활용
-- WHERE 절에 사용되는 컬럼에 인덱스 생성
CREATE INDEX idx_age ON users(age);
-- 이제 이 쿼리가 빨라집니다
DELETE FROM users WHERE age < 20;
2. 배치 처리
-- 나쁜 예: 반복문으로 하나씩 삽입
-- INSERT INTO users (name) VALUES ('A');
-- INSERT INTO users (name) VALUES ('B');
-- 좋은 예: 한 번에 여러 행 삽입
INSERT INTO users (name) VALUES ('A'), ('B'), ('C'), ('D');
3. 조건 최적화
-- 나쁜 예: 함수 사용
DELETE FROM users WHERE YEAR(created_at) = 2020;
-- 좋은 예: 인덱스 활용 가능
DELETE FROM users
WHERE created_at >= '2020-01-01' AND created_at < '2021-01-01';
8. 자주 발생하는 오류와 해결
오류 1: 외래키 제약 조건
-- 오류: 참조되는 데이터는 삭제 불가
DELETE FROM users WHERE id = 1;
-- ERROR: Cannot delete - foreign key constraint fails
-- 해결: 참조하는 데이터 먼저 삭제
DELETE FROM orders WHERE user_id = 1;
DELETE FROM users WHERE id = 1;
오류 2: 중복 키
-- 오류: 기본키 중복
INSERT INTO users (id, name) VALUES (1, '홍길동');
-- ERROR: Duplicate entry '1' for key 'PRIMARY'
-- 해결: 다른 ID 사용 또는 UPDATE 사용
UPDATE users SET name = '홍길동' WHERE id = 1;
오류 3: NULL 제약
-- 오류: NOT NULL 컬럼에 NULL 삽입
INSERT INTO users (name) VALUES (NULL);
-- ERROR: Column 'name' cannot be null
-- 해결: 값 제공
INSERT INTO users (name) VALUES ('이름없음');
9. 보안 Best Practices
SQL Injection 방지
-- 위험: 사용자 입력을 직접 쿼리에 포함
-- DELETE FROM users WHERE name = '" + userInput + "';
-- 안전: Prepared Statement 사용 (코드 예시)
Java 예시:
String sql = "DELETE FROM users WHERE name = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, userInput);
pstmt.executeUpdate();
Python 예시:
cursor.execute("DELETE FROM users WHERE name = %s", (user_input,))
10. 실습 문제
아래 users 테이블로 연습해보세요:
-- 테이블 생성
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
age INT,
status VARCHAR(20) DEFAULT 'ACTIVE',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
문제 1: 새로운 사용자 3명을 한 번에 추가하세요.
문제 2: 나이가 25세인 모든 사용자의 상태를 'VERIFIED'로 변경하세요.
문제 3: 이메일이 없는 사용자를 모두 삭제하세요.
문제 4: 모든 사용자의 나이를 1씩 증가시키세요.
문제 5: 'INACTIVE' 상태이면서 1년 이상 된 사용자를 삭제하세요.
마무리
INSERT, UPDATE, DELETE는 데이터베이스의 핵심 작업입니다.
기억해야 할 핵심:
- ✅ 항상 WHERE 절을 신중하게 작성하세요
- ✅ 중요한 작업 전에는 SELECT로 먼저 확인하세요
- ✅ 트랜잭션을 활용하여 데이터 무결성을 보장하세요
- ✅ 백업을 정기적으로 수행하세요
- ✅ Prepared Statement로 SQL Injection을 방지하세요