SQL 기본 문법 - 데이터베이스 조작의 핵심
개요
SQL(Structured Query Language)은 데이터베이스를 조작하는 표준 언어입니다:
- 데이터베이스 관리: 테이블 생성, 수정, 삭제
- 데이터 조작: 데이터 추가, 조회, 수정, 삭제
- Django 연동: Django ORM과 SQL 구문 비교
- 실무 활용: 실제 프로젝트에서의 SQL 활용
1. SQL 환경 설정
데이터베이스 파일 생성
- mysql.sqlite3 파일 생성
- table.sql 파일 생성 → Use Database mysql.sqlite3 연결 (마우스 오른쪽 버튼)
- Run Query (마우스 오른쪽 버튼 OR Ctrl+Shift+Enter)
기본 설정
1
2
3
4
5
| -- 데이터베이스 연결 확인
SELECT sqlite_version();
-- 현재 데이터베이스 정보 확인
PRAGMA database_list;
|
2. 테이블 생성 (CREATE TABLE)
기본 테이블 생성
1
2
3
4
5
6
| -- 기본 테이블 생성
CREATE TABLE Post(
id INTEGER,
title TEXT,
content TEXT
);
|
제약조건이 포함된 테이블 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| -- Post 테이블 생성 (제약조건 포함)
CREATE TABLE Post(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
title TEXT NOT NULL,
content TEXT NOT NULL
);
-- Comment 테이블 생성 (외래키 포함)
CREATE TABLE Comment(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
post_id INTEGER NOT NULL,
content TEXT NOT NULL,
FOREIGN KEY (post_id) REFERENCES Post (id)
);
|
제약조건 설명
- PRIMARY KEY: 기본키 (고유 식별자)
- AUTOINCREMENT: 자동 증가
- NOT NULL: NULL 값 허용하지 않음
- FOREIGN KEY: 외래키 (다른 테이블 참조)
3. 테이블 삭제 (DROP TABLE)
1
2
3
4
5
| -- 테이블 삭제
DROP TABLE Post;
-- 조건부 테이블 삭제 (테이블이 존재할 때만)
DROP TABLE IF EXISTS Post;
|
4. 테이블 변경 (ALTER TABLE)
컬럼 추가
1
2
3
| -- 컬럼 추가
ALTER TABLE Post
ADD COLUMN test TEXT;
|
컬럼 이름 변경
1
2
3
| -- 컬럼 이름 변경
ALTER TABLE Post
RENAME COLUMN test TO email;
|
컬럼 삭제
1
2
3
| -- 컬럼 삭제 (SQLite 3.35.0 이상)
ALTER TABLE Post
DROP COLUMN email;
|
5. 데이터 추가 (INSERT)
단일 데이터 추가
1
2
3
| -- 단일 데이터 추가
INSERT INTO Post (title, content)
VALUES ('first post', 'hihi');
|
다중 데이터 추가
1
2
3
4
5
6
| -- 다중 데이터 추가
INSERT INTO Post (title, content)
VALUES
('1', '1'),
('2', '2'),
('3', '3');
|
외래키가 있는 테이블에 데이터 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
| -- Comment 테이블에 데이터 추가
INSERT INTO Comment (post_id, content)
VALUES
(1, 'hello'),
(1, 'hello'),
(2, 'hello'),
(2, 'hello'),
(3, 'hello'),
(3, 'hello'),
(4, 'hello'),
(4, 'hello'),
(5, 'hello'),
(5, 'hello');
|
6. 데이터 조회 (SELECT)
기본 조회
1
2
3
4
5
6
7
8
| -- 모든 데이터 조회
SELECT * FROM Post;
-- 특정 컬럼만 조회
SELECT title FROM Post;
-- 여러 컬럼 조회
SELECT title, content FROM Post;
|
중복 제거
1
2
| -- 중복 제거하여 조회
SELECT DISTINCT content FROM Comment;
|
조건부 조회
1
2
3
4
5
6
7
| -- WHERE 조건 사용
SELECT * FROM Post WHERE id = 1;
SELECT * FROM Post WHERE title = 'first post';
-- 비교 연산자 사용
SELECT * FROM Post WHERE id > 2;
SELECT * FROM Post WHERE id BETWEEN 1 AND 3;
|
7. 데이터 수정 (UPDATE)
1
2
3
4
5
6
7
8
9
| -- 데이터 수정
UPDATE Post
SET title = 'updated title', content = 'updated content'
WHERE id = 1;
-- 여러 조건으로 수정
UPDATE Post
SET content = 'modified'
WHERE id IN (1, 2, 3);
|
8. 데이터 삭제 (DELETE)
1
2
3
4
5
6
7
8
| -- 특정 데이터 삭제
DELETE FROM Post WHERE id = 1;
-- 모든 데이터 삭제
DELETE FROM Post;
-- 조건부 삭제
DELETE FROM Post WHERE title = 'first post';
|
9. JOIN 연산
INNER JOIN
1
2
3
4
| -- Post와 Comment 테이블 조인
SELECT p.title, p.content, c.content as comment_content
FROM Post p
INNER JOIN Comment c ON p.id = c.post_id;
|
LEFT JOIN
1
2
3
4
| -- 모든 Post와 해당하는 Comment 조회
SELECT p.title, p.content, c.content as comment_content
FROM Post p
LEFT JOIN Comment c ON p.id = c.post_id;
|
10. 집계 함수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| -- COUNT: 개수 세기
SELECT COUNT(*) FROM Post;
SELECT COUNT(DISTINCT content) FROM Comment;
-- SUM, AVG, MIN, MAX
SELECT
COUNT(*) as total_posts,
AVG(LENGTH(content)) as avg_content_length
FROM Post;
-- GROUP BY 사용
SELECT post_id, COUNT(*) as comment_count
FROM Comment
GROUP BY post_id;
|
11. 정렬 및 제한
1
2
3
4
5
6
7
| -- ORDER BY: 정렬
SELECT * FROM Post ORDER BY id DESC;
SELECT * FROM Post ORDER BY title ASC, id DESC;
-- LIMIT: 결과 개수 제한
SELECT * FROM Post LIMIT 5;
SELECT * FROM Post LIMIT 5 OFFSET 10; -- 11번째부터 5개
|
12. Django와 SQL 연동
Django에서 SQL 직접 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| from django.db import connection
def execute_raw_sql():
"""Django에서 SQL 직접 실행"""
with connection.cursor() as cursor:
# 테이블 생성
cursor.execute("""
CREATE TABLE IF NOT EXISTS CustomTable(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
# 데이터 삽입
cursor.execute("""
INSERT INTO CustomTable (name) VALUES (%s)
""", ['Test Name'])
# 데이터 조회
cursor.execute("SELECT * FROM CustomTable")
results = cursor.fetchall()
return results
|
Django ORM과 SQL 비교
1
2
3
4
5
6
7
8
9
10
11
12
| # Django ORM
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
# ORM 쿼리
posts = Post.objects.filter(title__icontains='first')
# 해당하는 SQL
# SELECT * FROM Post WHERE title LIKE '%first%'
|
13. 실무 활용 팁
1. 인덱스 생성
1
2
3
4
5
6
| -- 인덱스 생성 (성능 향상)
CREATE INDEX idx_post_title ON Post(title);
CREATE INDEX idx_comment_post_id ON Comment(post_id);
-- 복합 인덱스
CREATE INDEX idx_post_title_content ON Post(title, content);
|
2. 뷰 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
| -- 뷰 생성
CREATE VIEW PostWithCommentCount AS
SELECT
p.id,
p.title,
p.content,
COUNT(c.id) as comment_count
FROM Post p
LEFT JOIN Comment c ON p.id = c.post_id
GROUP BY p.id, p.title, p.content;
-- 뷰 사용
SELECT * FROM PostWithCommentCount;
|
3. 트랜잭션 처리
1
2
3
4
5
6
7
8
9
10
11
12
| -- 트랜잭션 시작
BEGIN TRANSACTION;
-- 여러 작업 수행
INSERT INTO Post (title, content) VALUES ('Post 1', 'Content 1');
INSERT INTO Post (title, content) VALUES ('Post 2', 'Content 2');
-- 커밋 (변경사항 저장)
COMMIT;
-- 롤백 (변경사항 취소)
-- ROLLBACK;
|
4. 데이터 백업 및 복원
1
2
3
4
5
6
7
8
| -- 데이터 백업 (SQLite)
.backup main backup.db
-- 스키마만 백업
.schema Post
-- 데이터만 백업
.dump Post
|
14. 성능 최적화
1. 쿼리 최적화
1
2
3
4
5
| -- 비효율적인 쿼리
SELECT * FROM Post WHERE LOWER(title) = 'first post';
-- 효율적인 쿼리
SELECT * FROM Post WHERE title = 'First Post';
|
2. EXPLAIN QUERY PLAN 사용
1
2
3
4
5
| -- 쿼리 실행 계획 확인
EXPLAIN QUERY PLAN
SELECT * FROM Post p
JOIN Comment c ON p.id = c.post_id
WHERE p.title = 'first post';
|
15. 에러 처리 및 디버깅
1. 일반적인 에러들
1
2
3
4
5
6
7
8
9
10
11
| -- 테이블이 존재하지 않는 경우
-- Error: no such table: NonExistentTable
SELECT * FROM NonExistentTable;
-- 컬럼이 존재하지 않는 경우
-- Error: no such column: non_existent_column
SELECT non_existent_column FROM Post;
-- 제약조건 위반
-- Error: NOT NULL constraint failed
INSERT INTO Post (title) VALUES ('test'); -- content가 NOT NULL인데 누락
|
2. 디버깅 팁
1
2
3
4
5
6
7
8
| -- 현재 데이터베이스의 모든 테이블 확인
SELECT name FROM sqlite_master WHERE type='table';
-- 특정 테이블의 스키마 확인
.schema Post
-- 테이블 정보 확인
PRAGMA table_info(Post);
|
마무리
SQL 기본 문법을 통해 데이터베이스를 효과적으로 조작할 수 있습니다. 테이블 생성부터 데이터 조작까지의 기본적인 SQL 구문을 익히고, Django ORM과의 연동을 통해 실무에서 활용할 수 있는 기반을 마련했습니다.
성능 최적화, 에러 처리, 디버깅 등의 고급 기법을 통해 더욱 효율적인 데이터베이스 관리가 가능합니다.