PostgreSQL, MySQL, SQLite, 및 SQL Server를 지원하는 전문가 수준의 SQL 쿼리 작성, 최적화 및 데이터베이스 스키마 설계입니다. 데이터베이스 작업 시 다음을 위해 사용하세요: (1) JOIN, 서브쿼리, 윈도우 함수를 포함한 복잡한 SQL 쿼리 작성, (2) 느린 쿼리 최적화 및 실행 계획 분석, (3) 올바른 정규화를 적용한 데이터베이스 스키마 설계, (4) 인덱스 생성 및 쿼리 성능 개선, (5) 마이그레이션 작성 및 스키마 변경 처리, (6) SQL 에러 및 쿼리 문제 디버깅
/plugin marketplace add icartsh/icartsh_plugin/plugin install icartsh-plugin@icartsh-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
README.mdexamples/complex_queries.sqlexamples/migrations.sqlexamples/schema_examples.sqlreferences/advanced-patterns.mdreferences/best-practices.mdreferences/common-pitfalls.mdreferences/indexes-performance.mdreferences/query-optimization.mdscripts/sql_helper.pyPostgreSQL, MySQL, SQLite 및 SQL Server 전반에 걸친 SQL 데이터베이스의 작성, 최적화 및 관리를 위한 전문가 가이드입니다.
이 SKILL을 통해 다음을 수행할 수 있습니다:
적합한 사례: 복잡한 쿼리, JSON 데이터, 고급 기능, ACID 준수
pip install psycopg2-binary sqlalchemy
적합한 사례: 웹 애플리케이션, WordPress, 읽기 비중이 높은 워크로드
pip install mysql-connector-python sqlalchemy
적합한 사례: 로컬 개발, 임베디드 데이터베이스, 테스트
pip install sqlite3 # Python 내장
적합한 사례: 엔터프라이즈 애플리케이션, Windows 환경
pip install pyodbc sqlalchemy
-- 필터링이 포함된 단순 SELECT
SELECT
column1,
column2,
column3
FROM
table_name
WHERE
condition = 'value'
AND another_condition > 100
ORDER BY
column1 DESC
LIMIT 10;
-- INNER JOIN
SELECT
users.name,
orders.order_date,
orders.total_amount
FROM
users
INNER JOIN
orders ON users.id = orders.user_id
WHERE
orders.status = 'completed';
-- LEFT JOIN (주문이 없는 사용자를 포함하여 모두 조회)
SELECT
users.name,
COUNT(orders.id) as order_count,
COALESCE(SUM(orders.total_amount), 0) as total_spent
FROM
users
LEFT JOIN
orders ON users.id = orders.user_id
GROUP BY
users.id, users.name;
-- WHERE 절의 서브쿼리
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- CTE (가독성 향상을 위해 권장)
WITH high_value_customers AS (
SELECT
user_id,
SUM(total_amount) as lifetime_value
FROM orders
GROUP BY user_id
HAVING SUM(total_amount) > 1000
)
SELECT
users.name,
users.email,
hvc.lifetime_value
FROM users
INNER JOIN high_value_customers hvc ON users.id = hvc.user_id;
-- 그룹 내 순위 지정
SELECT
name,
department,
salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) as salary_rank
FROM
employees;
-- 누계 (Running totals)
SELECT
order_date,
total_amount,
SUM(total_amount) OVER (ORDER BY order_date) as running_total
FROM
orders;
-- 이동 평균 (Moving averages)
SELECT
order_date,
total_amount,
AVG(total_amount) OVER (
ORDER BY order_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) as moving_avg_7days
FROM
daily_sales;
더 복잡한 쿼리 패턴은 examples/complex_queries.sql을 참조하세요.
-- 쿼리 성능 분석
EXPLAIN ANALYZE
SELECT
users.name,
COUNT(orders.id) as order_count
FROM users
LEFT JOIN orders ON users.id = orders.user_id
GROUP BY users.id, users.name;
-- 확인할 내용:
-- - Seq Scan (나쁨) vs Index Scan (좋음)
-- - 높은 비용(cost) 수치
-- - 처리되는 대량의 행 수(row counts)
-- 나쁨: 인덱스 컬럼에 함수 사용
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
-- 좋음: 인덱스 컬럼을 가공하지 않음
SELECT * FROM users WHERE email = LOWER('user@example.com');
-- 나쁨: SELECT * 사용
SELECT * FROM large_table WHERE id = 123;
-- 좋음: 필요한 컬럼만 선택
SELECT id, name, email FROM large_table WHERE id = 123;
포괄적인 최적화 기법은 references/query-optimization.md를 참조하세요.
제1정규형 (1NF): 반복되는 그룹 제거, 원자성(atomic) 확보
-- 좋음: 주문 항목을 위한 별도 테이블 구성
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_name VARCHAR(100)
);
CREATE TABLE order_items (
order_item_id INT PRIMARY KEY,
order_id INT REFERENCES orders(order_id),
product_name VARCHAR(100)
);
제2정규형 (2NF): 기본키가 아닌 모든 속성이 기본키 전체에 의존해야 함
-- 좋음: 제품 정보를 분리하여 관리
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
product_price DECIMAL(10, 2)
);
CREATE TABLE order_items (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
제3정규형 (3NF): 이행적 종속성(transitive dependency)이 없어야 함
일대다 (One-to-Many):
CREATE TABLE authors (
author_id INT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100) UNIQUE
);
CREATE TABLE books (
book_id INT PRIMARY KEY,
title VARCHAR(200),
author_id INT NOT NULL,
published_date DATE,
FOREIGN KEY (author_id) REFERENCES authors(author_id)
);
다대다 (Many-to-Many):
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE courses (
course_id INT PRIMARY KEY,
course_name VARCHAR(100)
);
-- 교차(Junction) 테이블
CREATE TABLE enrollments (
enrollment_id INT PRIMARY KEY,
student_id INT NOT NULL,
course_id INT NOT NULL,
enrollment_date DATE,
grade CHAR(2),
FOREIGN KEY (student_id) REFERENCES students(student_id),
FOREIGN KEY (course_id) REFERENCES courses(course_id),
UNIQUE (student_id, course_id)
);
더 많은 스키마 패턴은 examples/schema_examples.sql을 참조하세요.
-- 단일 컬럼 인덱스
CREATE INDEX idx_users_email ON users(email);
-- 복합 인덱스 (컬럼 순서가 중요합니다!)
CREATE INDEX idx_orders_user_date ON orders(user_id, order_date);
-- 고유 인덱스
CREATE UNIQUE INDEX idx_users_username ON users(username);
-- 부분 인덱스 (PostgreSQL)
CREATE INDEX idx_active_users ON users(email) WHERE status = 'active';
인덱스가 필요한 경우:
인덱스를 피해야 하는 경우:
상세한 인덱스 전략은 references/indexes-performance.md를 참조하세요.
-- 1단계: nullable 컬럼으로 추가
ALTER TABLE users ADD COLUMN status VARCHAR(20);
-- 2단계: 기존 데이터 채우기
UPDATE users SET status = 'active' WHERE status IS NULL;
-- 3단계: NOT NULL 제약 조건 부여
ALTER TABLE users ALTER COLUMN status SET NOT NULL;
-- 4단계: 새 행을 위한 기본값 설정
ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active';
-- 롤백 계획
ALTER TABLE users DROP COLUMN status;
-- 좋음: 컬럼을 먼저 nullable로 추가한 뒤 데이터 채움
ALTER TABLE large_table ADD COLUMN new_column VARCHAR(100);
-- 대량 업데이트는 배치(batch) 단위로 수행
UPDATE large_table SET new_column = 'value' WHERE new_column IS NULL LIMIT 1000;
-- 완료될 때까지 반복
-- 그 다음 NOT NULL 설정
ALTER TABLE large_table ALTER COLUMN new_column SET NOT NULL;
추가 마이그레이션 패턴은 examples/migrations.sql을 참조하세요.
-- PostgreSQL
INSERT INTO users (user_id, name, email, updated_at)
VALUES (1, 'John Doe', 'john@example.com', NOW())
ON CONFLICT (user_id)
DO UPDATE SET
name = EXCLUDED.name,
email = EXCLUDED.email,
updated_at = NOW();
-- MySQL
INSERT INTO users (user_id, name, email, updated_at)
VALUES (1, 'John Doe', 'john@example.com', NOW())
ON DUPLICATE KEY UPDATE
name = VALUES(name),
email = VALUES(email),
updated_at = NOW();
-- 계층형 데이터 탐색
WITH RECURSIVE employee_hierarchy AS (
-- Anchor: 최상위 직원
SELECT id, name, manager_id, 1 as level
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Recursive: 이전 레벨에 보고하는 직원들
SELECT e.id, e.name, e.manager_id, eh.level + 1
FROM employees e
INNER JOIN employee_hierarchy eh ON e.manager_id = eh.id
)
SELECT * FROM employee_hierarchy ORDER BY level, name;
피벗 테이블, JSON 작업 및 벌크 작업을 포함한 고급 패턴은 references/advanced-patterns.md를 참조하세요.
모범 사례 적용 예시:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT NOT NULL,
order_date DATE NOT NULL DEFAULT CURRENT_DATE,
total_amount DECIMAL(10, 2) CHECK (total_amount >= 0),
status VARCHAR(20) CHECK (status IN ('pending', 'completed', 'cancelled')),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status ON orders(status);
포괄적인 모범 사례는 references/best-practices.md를 참조하세요.
다음을 주의하세요:
예시 - N+1 문제 피하기:
# 나쁨: N+1 쿼리
users = db.query("SELECT * FROM users")
for user in users:
orders = db.query("SELECT * FROM orders WHERE user_id = ?", user.id)
# 좋음: JOIN을 이용한 단일 쿼리
result = db.query("""
SELECT users.*, orders.*
FROM users
LEFT JOIN orders ON users.id = orders.user_id
""")
문제 해결 방법의 전체 목록은 references/common-pitfalls.md를 참조하세요.
헬퍼 스크립트 (scripts/):
sql_helper.py - 쿼리 빌딩, 스키마 내성 조사(introspection), 인덱스 분석 및 마이그레이션 보조 유틸리티예시 (examples/):
complex_queries.sql - CTE, 윈도우 함수, 서브쿼리를 활용한 고급 쿼리 패턴schema_examples.sql - 다양한 유스케이스를 위한 전체 스키마 설계 예시migrations.sql - 안전한 마이그레이션 패턴 및 무중단 기법참조 문서 (references/):
query-optimization.md - 포괄적인 쿼리 최적화 기법 및 EXPLAIN 분석indexes-performance.md - 상세 인덱스 전략, 유지보수 및 모니터링advanced-patterns.md - UPSERT, 벌크 작업, 피벗 테이블, JSON 작업, 재귀 쿼리best-practices.md - 전체 SQL 모범 사례 가이드common-pitfalls.md - 일반적인 실수와 방지 방법references/query-optimization.md를 확인하세요.examples/schema_examples.sql을 참조하세요.references/advanced-patterns.md를 확인하세요.scripts/sql_helper.py를 활용하세요.SQL 데이터베이스 작업 시:
마이그레이션 시: