⏱️ ~12 นาที

Database & SQL ใน Python

เก็บข้อมูลถาวรด้วย SQLite และภาษา SQL

ทำไมต้อง Database?

ในบทที่แล้วเราเก็บข้อมูลใน list ในหน่วยความจำ ปัญหาคือ: ปิดเซิร์ฟเวอร์ → ข้อมูลหายหมด

Database เก็บข้อมูล ถาวร บนดิสก์ ในบทนี้ใช้ SQLite เพราะ:

  • มีในตัว Python (โมดูล sqlite3) ไม่ต้องติดตั้งเพิ่ม
  • ✅ เก็บข้อมูลในไฟล์เดียว
  • ✅ ใช้ภาษา SQL เดียวกับ MySQL/PostgreSQL

ภาพ Database

เหมือนตาราง Excel — มี ตาราง (table), แถว (row), คอลัมน์ (column):

ตาราง products:

idnameprice
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/เครื่องมือคือ
SQLAlchemyORM ยอดนิยม เขียน Python แทน SQL
SQLModelผสม Pydantic + SQLAlchemy (โดยคน FastAPI)
PostgreSQLdatabase ระดับโปรดักชั่น แนะนำเมื่อเติบโต

สรุป

SQLใช้ทำอะไร
CREATE TABLEสร้างตาราง
INSERT INTOเพิ่ม
SELECTอ่าน
UPDATEแก้ (อย่าลืม WHERE)
DELETEลบ (อย่าลืม WHERE)

จบโมดูล Backend! บทหน้า: ทำความเข้าใจ HTML & CSS เพื่อทำ Frontend 🎨

อ่านจบแล้ว? ทำเครื่องหมายว่าเสร็จเพื่อบันทึกความคืบหน้า

🧠

แบบทดสอบ

ตอบให้ครบแล้วกด “ตรวจคำตอบ” เพื่อเช็คความเข้าใจ

  1. 1. โมดูลใดใน Python ใช้จัดการ SQLite โดยไม่ต้องติดตั้งเพิ่ม?

  2. 2. คำสั่ง SQL ใดใช้ดึงข้อมูลจากตาราง?

  3. 3. วิธีปลอดภัยที่สุดในการใส่ค่าจากผู้ใช้ลงใน SQL คือ?

กำลังโหลด…