Database & SQL ใน Python
เก็บข้อมูลถาวรด้วย SQLite และภาษา SQL
ทำไมต้อง Database?
ในบทที่แล้วเราเก็บข้อมูลใน list ในหน่วยความจำ ปัญหาคือ: ปิดเซิร์ฟเวอร์ → ข้อมูลหายหมด
Database เก็บข้อมูล ถาวร บนดิสก์ ในบทนี้ใช้ SQLite เพราะ:
- ✅ มีในตัว Python (โมดูล
sqlite3) ไม่ต้องติดตั้งเพิ่ม - ✅ เก็บข้อมูลในไฟล์เดียว
- ✅ ใช้ภาษา SQL เดียวกับ MySQL/PostgreSQL
ภาพ Database
เหมือนตาราง Excel — มี ตาราง (table), แถว (row), คอลัมน์ (column):
ตาราง products:
| id | name | price |
|---|---|---|
| 1 | กาแฟ | 80.0 |
| 2 | ชา | 60.0 |
SQL พื้นฐาน (CRUD)
-- สร้างตาราง
CREATE TABLE products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price REAL
);
-- เพิ่ม
INSERT INTO products (name, price) VALUES ('กาแฟ', 80.0);
-- อ่าน
SELECT * FROM products; -- ทั้งหมด
SELECT * FROM products WHERE price < 70; -- มีเงื่อนไข
-- แก้
UPDATE products SET price = 90 WHERE id = 1;
-- ลบ
DELETE FROM products WHERE id = 2;
⚠️ UPDATE/DELETE ต้องมี
WHEREไม่งั้นกระทบ ทุกแถว
ลองทำจริง: FastAPI + SQLite
import sqlite3
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
class Product(BaseModel):
name: str
price: float
# ฟังก์ชันเชื่อมต่อ database
def get_db():
conn = sqlite3.connect("shop.db")
conn.row_factory = sqlite3.Row # ให้ผลลัพธ์เข้าถึงแบบ dict ได้
return conn
# สร้างตารางตอนเริ่ม (ถ้ายังไม่มี)
@app.on_event("startup")
def startup():
conn = get_db()
conn.execute("""
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price REAL
)
""")
conn.commit()
conn.close()
# GET /products — ดูทั้งหมด
@app.get("/products")
def list_products():
conn = get_db()
rows = conn.execute("SELECT * FROM products").fetchall()
conn.close()
return [dict(r) for r in rows]
# POST /products — เพิ่มใหม่
@app.post("/products")
def create_product(product: Product):
conn = get_db()
cursor = conn.execute(
"INSERT INTO products (name, price) VALUES (?, ?)",
(product.name, product.price)
)
conn.commit()
new_id = cursor.lastrowid
conn.close()
return {"id": new_id, "name": product.name, "price": product.price}
# GET /products/{id} — ดูอันเดียว
@app.get("/products/{product_id}")
def get_product(product_id: int):
conn = get_db()
row = conn.execute(
"SELECT * FROM products WHERE id = ?", (product_id,)
).fetchone()
conn.close()
if row is None:
raise HTTPException(status_code=404, detail="ไม่พบสินค้า")
return dict(row)
# DELETE /products/{id} — ลบ
@app.delete("/products/{product_id}")
def delete_product(product_id: int):
conn = get_db()
conn.execute("DELETE FROM products WHERE id = ?", (product_id,))
conn.commit()
conn.close()
return {"message": "ลบแล้ว"}
รัน uvicorn main:app --reload แล้วทดสอบที่ /docs
ระวัง SQL Injection!
❌ อันตราย (ต่อสตริง):
conn.execute(f"SELECT * FROM users WHERE name = '{name}'")
✅ ปลอดภัย (? placeholder):
conn.execute("SELECT * FROM users WHERE name = ?", (name,))
อย่าต่อข้อมูลจากผู้ใช้เข้า SQL โดยตรง ใช้
?เสมอ
โครงสร้างที่ดีขึ้น: แยก layer
โปรเจกต์จริงมักแยก:
app/
├── main.py ← routes
├── database.py ← จัดการการเชื่อมต่อ
└── models.py ← โครงสร้างข้อมูล
เครื่องมือดู database
- DB Browser for SQLite — GUI ดูไฟล์
.dbฟรี - DBeaver — ดูได้หลายประเภท
ทางเลือกอื่น (ตอนเก่งขึ้น)
| ORM/เครื่องมือ | คือ |
|---|---|
| SQLAlchemy | ORM ยอดนิยม เขียน Python แทน SQL |
| SQLModel | ผสม Pydantic + SQLAlchemy (โดยคน FastAPI) |
| PostgreSQL | database ระดับโปรดักชั่น แนะนำเมื่อเติบโต |
สรุป
| SQL | ใช้ทำอะไร |
|---|---|
CREATE TABLE | สร้างตาราง |
INSERT INTO | เพิ่ม |
SELECT | อ่าน |
UPDATE | แก้ (อย่าลืม WHERE) |
DELETE | ลบ (อย่าลืม WHERE) |
จบโมดูล Backend! บทหน้า: ทำความเข้าใจ HTML & CSS เพื่อทำ Frontend 🎨
อ่านจบแล้ว? ทำเครื่องหมายว่าเสร็จเพื่อบันทึกความคืบหน้า
แบบทดสอบ
ตอบให้ครบแล้วกด “ตรวจคำตอบ” เพื่อเช็คความเข้าใจ
1. โมดูลใดใน Python ใช้จัดการ SQLite โดยไม่ต้องติดตั้งเพิ่ม?
2. คำสั่ง SQL ใดใช้ดึงข้อมูลจากตาราง?
3. วิธีปลอดภัยที่สุดในการใส่ค่าจากผู้ใช้ลงใน SQL คือ?
กำลังโหลด…