Bài 12: Kết nối SQLite với Python – Bước đầu xây dựng ứng dụng


I. Mục đích (Objectives)

Sau bài học này, người đọc sẽ:

  • Biết cách sử dụng thư viện sqlite3 (có sẵn trong Python) để kết nối vào file database.
  • Hiểu khái niệm Connection (Kết nối) và Cursor (Con trỏ thực thi).
  • Viết được script Python thực hiện trọn vẹn quy trình CRUD: Thêm, Xem, Sửa, Xóa dữ liệu trong SQLite.
  • Quan trọng: Hiểu và thực hành kỹ thuật Parameterized Query (Truy vấn tham số hóa) để chống lỗ hổng bảo mật SQL Injection – bài học vỡ lòng cho mọi lập trình viên.

II. Yêu cầu (Prerequisites)

  • Đã cài đặt Python (phiên bản 3.x trở lên).
  • Có sẵn trình soạn thảo code (VS Code, PyCharm hoặc đơn giản là IDLE).
  • File cơ sở dữ liệu QuanLyLopHoc.db (đã tạo ở các bài trước).

III. Nội dung chi tiết (Detailed Content)

1. “Cặp đôi hoàn hảo” Python và SQLite

Tại sao chúng ta chọn Python? Vì Python hỗ trợ SQLite “tận răng”. Bạn không cần cài đặt driver (pip install…) như khi làm việc với MySQL hay PostgreSQL. Thư viện sqlite3 đã được tích hợp sẵn trong bộ cài chuẩn của Python (“Batteries Included”).

2. Quy trình kết nối tiêu chuẩn (The Workflow)

Để thao tác với DB, chương trình Python luôn tuân theo 3 bước:

  1. Connect: Mở đường dây liên lạc tới file .db.
  2. Cursor: Tạo một “con trỏ” để chạy đi chạy lại đưa lệnh SQL và lấy kết quả về.
  3. Close: Đóng kết nối để giải phóng tài nguyên.

Code mẫu kết nối:

import sqlite3

# 1. Kết nối đến database
# Nếu file chưa tồn tại, nó sẽ tự tạo mới. Nếu có rồi, nó sẽ mở ra.
conn = sqlite3.connect('QuanLyLopHoc.db')

# 2. Tạo con trỏ (Cursor)
cursor = conn.cursor()

# ... Viết lệnh xử lý ở đây ...

# 3. Đóng kết nối
conn.close()

3. Thực hành: Đọc dữ liệu (SELECT)

Chúng ta sẽ viết code để in danh sách học sinh ra màn hình console.

import sqlite3

conn = sqlite3.connect('QuanLyLopHoc.db')
cursor = conn.cursor()

# Thực thi câu lệnh SQL
cursor.execute("SELECT * FROM HocSinh WHERE diem_tb >= 8.0")

# Lấy tất cả kết quả trả về
danh_sach = cursor.fetchall()

print(f"Tìm thấy {len(danh_sach)} học sinh giỏi:")

# Duyệt vòng lặp để in đẹp hơn
for hs in danh_sach:
    # hs là một tuple: (id, ho_ten, diem_tb, ...)
    print(f"- ID: {hs[0]} | Tên: {hs[1]} | Điểm: {hs[2]}")

conn.close()
  • cursor.execute(): Gửi lệnh SQL sang Database.
  • cursor.fetchall(): Lấy toàn bộ dữ liệu về dưới dạng một list các tuple.

4. Thực hành: Ghi dữ liệu (INSERT/UPDATE) và lệnh Commit

Khác với việc đọc, khi ghi dữ liệu, bạn cần thêm một bước xác nhận là commit(). Nếu quên bước này, dữ liệu sẽ không được lưu (giống như soạn văn bản mà quên nhấn Save).

import sqlite3

conn = sqlite3.connect('QuanLyLopHoc.db')
cursor = conn.cursor()

# Thêm một học sinh mới
sql_insert = "INSERT INTO HocSinh (ho_ten, diem_tb, ma_lop_id) VALUES ('Em Mới', 7.5, 1)"
cursor.execute(sql_insert)

# QUAN TRỌNG: Xác nhận lưu thay đổi
conn.commit()

print("Đã thêm thành công!")
conn.close()

5. Cảnh báo bảo mật: SQL Injection (Dành cho Kỹ sư phần mềm tương lai)

Đây là phần quan trọng nhất bài viết. Giả sử bạn cho người dùng nhập tên để tìm kiếm.
Cách làm SAI (Nguy hiểm): Cộng chuỗi trực tiếp.

ten_can_tim = input("Nhập tên: ")
# NGUY HIỂM: Nếu hacker nhập: ' OR 1=1 --
sql = f"SELECT * FROM HocSinh WHERE ho_ten = '{ten_can_tim}'"
cursor.execute(sql)

-> Hacker có thể xem toàn bộ dữ liệu hoặc xóa sạch bảng của bạn!
Cách làm ĐÚNG (An toàn): Sử dụng Placeholder (?).

ten_can_tim = input("Nhập tên: ")

# Dấu ? là vị trí giữ chỗ. Python sẽ tự động xử lý ký tự đặc biệt để an toàn.
sql = "SELECT * FROM HocSinh WHERE ho_ten = ?"

# Truyền tham số dưới dạng tuple (có dấu phẩy cuối nếu chỉ có 1 phần tử)
cursor.execute(sql, (ten_can_tim,))

-> Quy tắc vàng: Không bao giờ đưa trực tiếp biến của người dùng vào chuỗi SQL. Hãy luôn dùng dấu ?.

6. Code tối ưu: Sử dụng with statement

Để tránh quên đóng kết nối (conn.close()), Python khuyên dùng từ khóa with. Kết nối sẽ tự động đóng khi chạy xong khối lệnh, kể cả khi có lỗi xảy ra.

import sqlite3

with sqlite3.connect('QuanLyLopHoc.db') as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM LopHoc")
    rows = cursor.fetchall()
    for row in rows:
        print(row)
# Ra khỏi khối with, kết nối tự động đóng. An toàn tuyệt đối.

IV. Tổng kết (Summary)

Hôm nay bạn đã chính thức trở thành một lập trình viên Database:

  1. Biết cách dùng sqlite3 để kết nối.
  2. Biết lấy dữ liệu (fetchall) và ghi dữ liệu (commit).
  3. Biết bảo vệ ứng dụng khỏi hacker bằng Parameterized Query (?).

Bài viết này là nền tảng để bạn xây dựng các ứng dụng lớn hơn như Tool quản lý điểm, App từ điển, hay Website cá nhân.
Trong bài tiếp theo, với thế mạnh của bạn là C# (như bạn đã chia sẻ ở phần giới thiệu), chúng ta sẽ xem xét cách kết nối SQLite với ngôn ngữ C# để tạo ứng dụng Windows Form/WPF. Hẹn gặp lại các bạn trong Bài 13: Kết nối SQLite với C# – Xây dựng ứng dụng Desktop.

You may also like...

Để lại một bình luận