一、什麼是 SQLite?
SQLite 是一種輕量型的關聯式資料庫。它不需要另外架設資料庫伺服器,就能將資料儲存在一個資料庫檔案中,因此很適合拿來學習 SQL,或用在小型專案。
之前使用的 CSV 是以表格形式儲存資料,而 SQLite 可以讓我們使用 SQL 指令管理資料。
例如,假設我有一份書籍資料:
如果資料存在 CSV 裡,我可以用 Pandas 讀取和分析;如果資料存在 SQLite 裡,就可以透過 SQL 查詢價格、篩選評分,或新增和修改書籍資料。
今天會使用的工具如下:
Python:負責處理資料和執行程式。
SQLite:儲存書籍資料。
SQL:對資料庫進行新增、查詢和管理。
Google Colab:執行今天的程式。
二、使用 Python 建立 SQLite 資料庫
Python 內建 sqlite3 模組,不需要另外安裝套件,就能操作 SQLite。
首先,在 Google Colab 執行以下程式:
import sqlite3
conn = sqlite3.connect("books.db")
cursor = conn.cursor()
print("SQLite 資料庫連線成功!")
執行後,程式會建立一個名為 books.db 的資料庫檔案,並建立資料庫連線。
這裡有兩個重要的物件:
conn 是資料庫連線,負責與資料庫互動,以及提交交易或關閉連線。
cursor 則是用來執行 SQL 指令的物件,例如建立資料表、查詢資料或新增紀錄。
要注意,在 Google Colab 中,這個檔案預設儲存在目前的執行環境裡。如果 Colab 執行環境被重設,檔案可能會消失,所以重要資料之後需要另外下載或保存到持久化儲存空間。
三、建立書籍資料表
建立資料庫之後,接下來需要建立資料表。
資料表可以想成 Excel 中的一張工作表,每一列代表一筆紀錄,每一欄則代表一種資料。
今天建立的資料表叫做 books,包含以下欄位:
欄位
資料型態
用途
id
INTEGER
書籍編號
title
TEXT
書名
price
REAL
價格
rating
INTEGER
評分
接著使用 SQL 建立資料表:
cursor.execute("""
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
price REAL,
rating INTEGER
)
""")
conn.commit()
print("books 資料表建立完成!")
這段程式中有幾個需要理解的語法。
CREATE TABLE 是建立資料表的指令。
IF NOT EXISTS 表示如果資料表已經存在,就不會再次建立同名資料表。
PRIMARY KEY 表示主鍵,用來識別每一筆紀錄。這裡使用 AUTOINCREMENT,讓新增資料時可以自動產生編號。
TEXT 用來儲存文字,REAL 用來儲存數值,INTEGER 則用來儲存整數。
NOT NULL 表示這個欄位不能是空值。
最後的 conn.commit() 會提交目前的資料庫交易,讓變更正式寫入資料庫。
四、新增書籍資料
資料表建立完成後,就可以開始新增資料。
books = [
("Book A", 15.99, 5),
("Book B", 25.50, 4),
("Book C", 8.99, 3),
("Book D", 45.00, 5),
("Book E", 32.99, 2)
]
cursor.executemany("""
INSERT INTO books (title, price, rating)
VALUES (?, ?, ?)
""", books)
conn.commit()
print("書籍資料新增完成!")
這裡使用 executemany(),一次新增多筆書籍資料,不必每一筆都分開執行 SQL。
另外,VALUES (?, ?, ?) 中的問號是參數佔位符,實際的值會由 books 清單提供。
使用參數化查詢可以避免直接拼接資料所造成的 SQL 注入風險,也能讓程式更容易維護。
需要注意的是,如果重複執行這段新增程式,資料也會再次寫入。若希望可以反覆執行而不重複新增,就需要進一步設計唯一識別條件或其他防重複機制。
五、查詢資料庫中的書籍
新增資料之後,接下來就要確認資料是否真的寫入資料庫。
最基本的查詢方式是使用 SELECT:
cursor.execute("SELECT * FROM books")
rows = cursor.fetchall()
for row in rows:
print(row)
SELECT * FROM books 表示查詢 books 資料表中的所有欄位和紀錄。
fetchall() 則會取回查詢結果中的所有資料。
輸出結果會類似以下內容:
(1, 'Book A', 15.99, 5)
(2, 'Book B', 25.5, 4)
(3, 'Book C', 8.99, 3)
(4, 'Book D', 45.0, 5)
(5, 'Book E', 32.99, 2)
每一筆資料都會包含 id、title、price 和 rating。
如果只想查詢書名和價格,可以指定需要的欄位:
cursor.execute("""
SELECT title, price
FROM books
""")
for row in cursor.fetchall():
print(row)
這樣就不必把整張資料表的所有欄位都取出來。
六、使用 SQL 篩選價格較高的書籍
前幾天,我曾經使用 Pandas 篩選符合條件的書籍。現在也可以透過 SQL 完成相同的工作。
例如,查詢價格大於 20 的書籍:
cursor.execute("""
SELECT title, price, rating
FROM books
WHERE price > ?
""", (20,))
for row in cursor.fetchall():
print(row)
這裡的 WHERE 是條件篩選語法,而 price > ? 表示只取得價格大於指定數值的紀錄。
因為 SQL 使用參數佔位符,所以傳入單一參數時,要寫成 (20,)。這個逗號很重要,因為它代表這是一個只有一個元素的 tuple。
如果想按照價格由高到低排列,可以加上 ORDER BY:
cursor.execute("""
SELECT title, price
FROM books
WHERE price > ?
ORDER BY price DESC
""", (20,))
for row in cursor.fetchall():
print(row)
ORDER BY price DESC 表示依照價格遞減排序,也就是價格最高的書會排在最前面。
如果想由低到高排列,則可以使用 ASC。
七、使用 SQL 計算平均價格
SQLite 不只能查詢個別紀錄,也可以直接在資料庫中進行統計。
例如,計算全部書籍的平均價格:
cursor.execute("""
SELECT AVG(price)
FROM books
""")
average_price = cursor.fetchone()[0]
print("平均價格:", round(average_price, 2))
這裡使用 AVG() 計算平均值,而 fetchone() 只會取回一筆結果。
除了平均值,也可以計算書籍數量、最高價格和最低價格:
cursor.execute("""
SELECT
COUNT(*) AS book_count,
AVG(price) AS average_price,
MAX(price) AS maximum_price,
MIN(price) AS minimum_price
FROM books
""")
result = cursor.fetchone()
print("書籍數量:", result[0])
print("平均價格:", round(result[1], 2))
print("最高價格:", result[2])
print("最低價格:", result[3])
這裡使用了四個常見的 SQL 聚合函式:
COUNT():計算紀錄數量。
AVG():計算平均值。
MAX():找出最大值。
MIN():找出最小值。
這些功能和之前在 Pandas 中學過的統計操作很相似,只是現在改成由 SQL 直接在資料庫中處理。
八、將前幾天的 Pandas 資料匯入 SQLite
前面先使用模擬資料練習資料庫操作。接下來,可以把前幾天清理完成的 DataFrame 寫入 SQLite。
假設目前已經有一個整理好的 df,而且其中包含 title、price 和 rating 三個欄位,就可以使用 Pandas 的 to_sql()。
required_columns = ["title", "price", "rating"]
print(df[required_columns].head())
確認欄位與資料格式沒有問題後,再執行:
df[["title", "price", "rating"]].to_sql(
"scraped_books",
conn,
if_exists="replace",
index=False
)
print("Pandas 資料已匯入 SQLite!")
這裡建立的資料表名稱是 scraped_books。
if_exists="replace" 表示如果同名資料表已經存在,就先刪除舊表再建立新表。因此,這個選項適合目前的完整重建示範,但不能隨意用在需要保留既有資料的正式系統。
如果想在既有資料表中追加資料,可以改成 if_exists="append";不過,追加前仍要確認資料表結構與欄位型態相容,也要避免重複匯入相同紀錄。
匯入後,可以使用 SQL 查詢:
cursor.execute("""
SELECT title, price, rating
FROM scraped_books
LIMIT 5
""")
for row in cursor.fetchall():
print(row)
LIMIT 5 表示只取出最多五筆資料,方便快速檢查匯入結果。
九、關閉資料庫連線
完成操作後,記得關閉資料庫連線:
conn.close()
print("資料庫連線已關閉!")
這是資料庫程式的一個基本習慣。如果後續還要繼續執行 SQL,就需要重新建立連線,並取得新的游標。
在實際專案中,也可以進一步使用 try/finally 或 with 來管理資源,避免程式發生錯誤時沒有妥善處理連線。