INSERT: 데이터 삽입
-- 단일 행 삽입
INSERT INTO employees (name, department, salary, hire_date)
VALUES ('신입사원', '개발팀', 3500000, '2026-04-21');
-- 여러 행 한 번에
INSERT INTO employees (name, department, salary, hire_date)
VALUES
('김A', '개발팀', 4000000, '2026-04-21'),
('이B', '마케팅팀', 3800000, '2026-04-21'),
('박C', '디자인팀', 4200000, '2026-04-21');
-- 삽입 후 생성된 ID 반환 (PostgreSQL)
INSERT INTO employees (name, department, salary)
VALUES ('정D', '개발팀', 4500000)
RETURNING id, name;
UPDATE: 데이터 수정
-- 특정 행 수정 (WHERE 필수!)
UPDATE employees
SET salary = 5500000
WHERE id = 1;
-- 여러 열 동시 수정
UPDATE employees
SET
salary = salary * 1.1, -- 10% 인상
department = '시니어개발팀'
WHERE department = '개발팀' AND salary < 5000000;
-- 결과 확인
UPDATE employees
SET salary = 6000000
WHERE id = 2
RETURNING id, name, salary;
-- ⚠️ WHERE 없으면 모든 행 수정!
-- UPDATE employees SET salary = 0; -- 전 직원 급여 0으로!
DELETE: 데이터 삭제
-- 특정 행 삭제
DELETE FROM employees WHERE id = 10;
-- 조건에 맞는 여러 행
DELETE FROM employees
WHERE hire_date < '2020-01-01' AND is_active = FALSE;
-- 삭제된 행 반환
DELETE FROM employees WHERE id = 5
RETURNING *;
-- 테이블 전체 비우기 (빠른 방법)
TRUNCATE TABLE employees;
TRUNCATE TABLE employees RESTART IDENTITY; -- ID 시퀀스도 초기화
트랜잭션
여러 작업을 하나의 단위로 묶어 모두 성공하거나 모두 실패하게 합니다.
-- 계좌 이체 예시
BEGIN;
UPDATE accounts SET balance = balance - 10000 WHERE id = 1; -- A 출금
UPDATE accounts SET balance = balance + 10000 WHERE id = 2; -- B 입금
-- 잔액 확인
SELECT id, balance FROM accounts WHERE id IN (1, 2);
-- 문제 없으면
COMMIT;
-- 문제 있으면
ROLLBACK;
SAVEPOINT
트랜잭션 내 중간 저장점을 설정합니다.
BEGIN;
INSERT INTO orders (customer_id, amount) VALUES (1, 50000);
SAVEPOINT after_order; -- 저장점
INSERT INTO order_items (order_id, product_id) VALUES (LASTVAL(), 99);
-- 실패 시 order는 살리고 item만 취소
ROLLBACK TO SAVEPOINT after_order;
COMMIT;
UPSERT: 있으면 UPDATE, 없으면 INSERT
-- ON CONFLICT DO UPDATE (PostgreSQL)
INSERT INTO user_settings (user_id, theme, language)
VALUES (1, 'dark', 'ko')
ON CONFLICT (user_id)
DO UPDATE SET
theme = EXCLUDED.theme,
language = EXCLUDED.language,
updated_at = NOW();
-- ON CONFLICT DO NOTHING (무시)
INSERT INTO email_subscribers (email)
VALUES ('kim@example.com')
ON CONFLICT (email) DO NOTHING;
데이터 변경 안전 체크리스트
-- ✅ UPDATE/DELETE 전 SELECT로 대상 확인
SELECT * FROM employees WHERE department = '구개발팀';
-- 확인 후 UPDATE
UPDATE employees SET department = '개발팀' WHERE department = '구개발팀';
-- ✅ 트랜잭션 사용
BEGIN;
DELETE FROM old_logs WHERE created_at < NOW() - INTERVAL '1 year';
-- 삭제된 수 확인
SELECT ROW_COUNT(); -- MySQL
-- RETURNING 으로 확인
COMMIT;
정리
| 명령어 | 역할 |
|---|---|
INSERT INTO ... VALUES | 행 삽입 |
INSERT ... RETURNING | 삽입 후 값 반환 |
UPDATE ... SET ... WHERE | 행 수정 |
DELETE FROM ... WHERE | 행 삭제 |
TRUNCATE | 테이블 전체 삭제 |
BEGIN/COMMIT/ROLLBACK | 트랜잭션 |
ON CONFLICT DO UPDATE | UPSERT |
다음 편에서는 DDL과 인덱스 — 테이블 구조를 설계하고 쿼리 성능을 높이는 방법을 배웁니다.