Python+sqlite3操作本地SQLite數(shù)據(jù)庫(kù)的實(shí)戰(zhàn)指南
對(duì)于 Python 后端初學(xué)者來(lái)說(shuō),數(shù)據(jù)庫(kù)操作是必須掌握的基礎(chǔ)能力。很多 Web 項(xiàng)目、接口服務(wù)、爬蟲(chóng)程序、桌面工具都會(huì)涉及數(shù)據(jù)的保存、查詢和更新。
如果你剛開(kāi)始學(xué)習(xí)數(shù)據(jù)庫(kù),不一定要馬上安裝 MySQL、PostgreSQL 這類(lèi)獨(dú)立數(shù)據(jù)庫(kù)服務(wù)。Python 標(biāo)準(zhǔn)庫(kù)自帶的 sqlite3 就可以直接操作 SQLite 本地?cái)?shù)據(jù)庫(kù),非常適合學(xué)習(xí) SQL、練習(xí) CRUD、開(kāi)發(fā)小型本地項(xiàng)目。
本文將通過(guò)一個(gè)“用戶信息管理”的例子,帶你完成:
sqlite3庫(kù)介紹- 創(chuàng)建 SQLite 數(shù)據(jù)庫(kù)
- 創(chuàng)建數(shù)據(jù)表
- 插入數(shù)據(jù)
- 查詢數(shù)據(jù)
- 修改數(shù)據(jù)
- 刪除數(shù)據(jù)
- Python ORM 思想簡(jiǎn)單介紹
- 完整 CRUD 演示代碼
一、sqlite3 庫(kù)介紹
sqlite3 是 Python 標(biāo)準(zhǔn)庫(kù)自帶的 SQLite 數(shù)據(jù)庫(kù)操作模塊,不需要額外安裝。
SQLite 是一種輕量級(jí)嵌入式數(shù)據(jù)庫(kù),它的特點(diǎn)是:
- 不需要單獨(dú)啟動(dòng)數(shù)據(jù)庫(kù)服務(wù)
- 數(shù)據(jù)保存在本地
.db文件中 - 適合學(xué)習(xí)、測(cè)試、小型工具、桌面程序和輕量級(jí)后端項(xiàng)目
- 支持常見(jiàn) SQL 語(yǔ)句,例如
CREATE TABLE、INSERT、SELECT、UPDATE、DELETE
在 Python 中使用 SQLite,只需要導(dǎo)入:
import sqlite3
一個(gè)典型的數(shù)據(jù)庫(kù)操作流程如下:
import sqlite3
conn = sqlite3.connect("demo.db")
cursor = conn.cursor()
cursor.execute("SELECT sqlite_version()")
print(cursor.fetchone())
conn.close()
這里有幾個(gè)重要概念:
connect():連接數(shù)據(jù)庫(kù),如果數(shù)據(jù)庫(kù)文件不存在,會(huì)自動(dòng)創(chuàng)建connection:數(shù)據(jù)庫(kù)連接對(duì)象,通常命名為conncursor:游標(biāo)對(duì)象,用來(lái)執(zhí)行 SQL 語(yǔ)句execute():執(zhí)行 SQLcommit():提交事務(wù),讓新增、修改、刪除真正生效close():關(guān)閉數(shù)據(jù)庫(kù)連接
二、創(chuàng)建數(shù)據(jù)庫(kù)
使用 SQLite 創(chuàng)建數(shù)據(jù)庫(kù)非常簡(jiǎn)單,只需要連接一個(gè) .db 文件即可。
import sqlite3
conn = sqlite3.connect("student.db")
conn.close()
運(yùn)行后,當(dāng)前目錄下會(huì)生成一個(gè) student.db 文件。
如果文件已經(jīng)存在,sqlite3.connect() 會(huì)直接連接這個(gè)數(shù)據(jù)庫(kù);如果文件不存在,就會(huì)自動(dòng)創(chuàng)建。
在實(shí)際項(xiàng)目中,也可以把數(shù)據(jù)庫(kù)文件放到指定目錄:
conn = sqlite3.connect(r"D:\data\student.db")
Windows 路徑前面加 r,可以避免反斜杠被當(dāng)作轉(zhuǎn)義字符。
三、創(chuàng)建數(shù)據(jù)表
數(shù)據(jù)庫(kù)文件創(chuàng)建好以后,還需要?jiǎng)?chuàng)建數(shù)據(jù)表。數(shù)據(jù)表類(lèi)似 Excel 中的一張工作表,用來(lái)存儲(chǔ)某一類(lèi)數(shù)據(jù)。
下面創(chuàng)建一張 users 表,用來(lái)保存用戶信息:
import sqlite3
conn = sqlite3.connect("app.db")
cursor = conn.cursor()
sql = """
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
email TEXT UNIQUE,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
"""
cursor.execute(sql)
conn.commit()
conn.close()
字段說(shuō)明:
id:用戶編號(hào),主鍵,自增name:用戶名,不能為空age:年齡,整數(shù)類(lèi)型email:郵箱,唯一created_at:創(chuàng)建時(shí)間,默認(rèn)使用當(dāng)前時(shí)間
CREATE TABLE IF NOT EXISTS 的意思是:如果表不存在就創(chuàng)建,如果已經(jīng)存在就不重復(fù)創(chuàng)建,避免程序重復(fù)運(yùn)行時(shí)報(bào)錯(cuò)。
四、插入數(shù)據(jù)
插入數(shù)據(jù)使用 INSERT INTO 語(yǔ)句。
import sqlite3
conn = sqlite3.connect("app.db")
cursor = conn.cursor()
sql = "INSERT INTO users (name, age, email) VALUES (?, ?, ?)"
cursor.execute(sql, ("張三", 22, "zhangsan@example.com"))
conn.commit()
conn.close()
這里需要重點(diǎn)注意:推薦使用 ? 占位符傳參,而不是直接拼接字符串。
推薦寫(xiě)法:
cursor.execute(
"INSERT INTO users (name, age, email) VALUES (?, ?, ?)",
("李四", 25, "lisi@example.com")
)
不推薦寫(xiě)法:
name = "李四"
sql = "INSERT INTO users (name) VALUES ('" + name + "')"
字符串拼接 SQL 容易出現(xiàn) SQL 注入風(fēng)險(xiǎn),也容易因?yàn)橐?hào)、特殊字符導(dǎo)致 SQL 報(bào)錯(cuò)。
如果要一次插入多條數(shù)據(jù),可以使用 executemany():
users = [
("王五", 28, "wangwu@example.com"),
("趙六", 30, "zhaoliu@example.com"),
("錢(qián)七", 24, "qianqi@example.com")
]
cursor.executemany(
"INSERT INTO users (name, age, email) VALUES (?, ?, ?)",
users
)
conn.commit()
五、查詢數(shù)據(jù)
查詢數(shù)據(jù)使用 SELECT 語(yǔ)句。
查詢所有用戶:
cursor.execute("SELECT id, name, age, email, created_at FROM users")
rows = cursor.fetchall()
for row in rows:
print(row)
fetchall() 會(huì)獲取所有查詢結(jié)果,返回一個(gè)列表,每一行是一個(gè)元組。
如果只想查詢一條數(shù)據(jù),可以使用 fetchone():
cursor.execute("SELECT id, name, age, email FROM users WHERE id = ?", (1,))
user = cursor.fetchone()
print(user)
注意 (1,) 不是寫(xiě)錯(cuò)了。Python 中只有一個(gè)元素的元組,必須加逗號(hào)。
也可以按條件查詢:
cursor.execute(
"SELECT id, name, age, email FROM users WHERE age >= ?",
(25,)
)
rows = cursor.fetchall()
六、修改數(shù)據(jù)
修改數(shù)據(jù)使用 UPDATE 語(yǔ)句。
下面把 id=1 的用戶年齡改為 23:
cursor.execute(
"UPDATE users SET age = ? WHERE id = ?",
(23, 1)
)
conn.commit()
如果想同時(shí)修改多個(gè)字段,可以這樣寫(xiě):
cursor.execute(
"UPDATE users SET name = ?, email = ? WHERE id = ?",
("張三豐", "zhangsanfeng@example.com", 1)
)
conn.commit()
執(zhí)行 UPDATE 時(shí)一定要小心 WHERE 條件。如果沒(méi)有 WHERE,可能會(huì)把整張表的數(shù)據(jù)都修改掉。
七、刪除數(shù)據(jù)
刪除數(shù)據(jù)使用 DELETE 語(yǔ)句。
刪除 id=1 的用戶:
cursor.execute("DELETE FROM users WHERE id = ?", (1,))
conn.commit()
同樣要注意:DELETE 語(yǔ)句必須謹(jǐn)慎使用 WHERE 條件。
危險(xiǎn)寫(xiě)法:
cursor.execute("DELETE FROM users")
這會(huì)刪除 users 表中的所有數(shù)據(jù)。
如果只是想清空測(cè)試數(shù)據(jù),可以明確知道后果后再執(zhí)行。
八、事務(wù)和異常處理
在數(shù)據(jù)庫(kù)操作中,新增、修改、刪除都需要提交事務(wù)。
如果執(zhí)行成功,就調(diào)用:
conn.commit()
如果執(zhí)行失敗,可以回滾:
conn.rollback()
更推薦使用 try...except...finally 管理數(shù)據(jù)庫(kù)連接:
import sqlite3
conn = None
try:
conn = sqlite3.connect("app.db")
cursor = conn.cursor()
cursor.execute(
"INSERT INTO users (name, age, email) VALUES (?, ?, ?)",
("測(cè)試用戶", 20, "test@example.com")
)
conn.commit()
except sqlite3.Error as e:
if conn:
conn.rollback()
print("數(shù)據(jù)庫(kù)操作失敗:", e)
finally:
if conn:
conn.close()
這樣可以避免程序異常時(shí)數(shù)據(jù)庫(kù)連接沒(méi)有關(guān)閉。
九、Python ORM 思想簡(jiǎn)單介紹
前面我們直接寫(xiě) SQL 操作數(shù)據(jù)庫(kù),這種方式直觀、靈活,也適合初學(xué)者理解數(shù)據(jù)庫(kù)底層邏輯。
在真實(shí)后端項(xiàng)目中,還經(jīng)常會(huì)使用 ORM。
ORM 的全稱(chēng)是 Object Relational Mapping,中文通常叫“對(duì)象關(guān)系映射”。它的核心思想是:
把數(shù)據(jù)庫(kù)中的表映射成 Python 類(lèi),把表中的一行數(shù)據(jù)映射成 Python 對(duì)象,把字段映射成對(duì)象屬性。
例如數(shù)據(jù)庫(kù)中有一張 users 表:
users 表 id | name | age | email
在 ORM 中,可能會(huì)定義一個(gè) User 類(lèi):
class User:
def __init__(self, id, name, age, email):
self.id = id
self.name = name
self.age = age
self.email = email
查詢數(shù)據(jù)庫(kù)后,可以把一行數(shù)據(jù)轉(zhuǎn)換成對(duì)象:
row = (1, "張三", 22, "zhangsan@example.com") user = User(row[0], row[1], row[2], row[3]) print(user.name)
這樣做的好處是:
- 代碼更接近面向?qū)ο髮?xiě)法
- 業(yè)務(wù)層可以少寫(xiě) SQL
- 數(shù)據(jù)結(jié)構(gòu)更清晰
- 大項(xiàng)目中更容易維護(hù)
Python 中常見(jiàn) ORM 框架包括:
- SQLAlchemy
- Django ORM
- Peewee
不過(guò),建議初學(xué)者先掌握基礎(chǔ) SQL 和 sqlite3,再學(xué)習(xí) ORM。因?yàn)?ORM 本質(zhì)上也是幫你生成和執(zhí)行 SQL,如果完全不了解 SQL,后面排查問(wèn)題會(huì)比較困難。
十、完整 CRUD 演示代碼
下面是一份完整示例代碼,包含創(chuàng)建數(shù)據(jù)庫(kù)、創(chuàng)建數(shù)據(jù)表、插入數(shù)據(jù)、查詢數(shù)據(jù)、修改數(shù)據(jù)、刪除數(shù)據(jù),以及一個(gè)簡(jiǎn)單的對(duì)象轉(zhuǎn)換示例。
你可以保存為 sqlite_crud_demo.py 后直接運(yùn)行。
import sqlite3
from dataclasses import dataclass
DB_NAME = "app.db"
@dataclass
class User:
id: int
name: str
age: int
email: str
created_at: str
def get_connection():
return sqlite3.connect(DB_NAME)
def create_table():
conn = get_connection()
cursor = conn.cursor()
sql = """
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
email TEXT UNIQUE,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
"""
cursor.execute(sql)
conn.commit()
conn.close()
def insert_user(name, age, email):
conn = get_connection()
cursor = conn.cursor()
try:
cursor.execute(
"INSERT INTO users (name, age, email) VALUES (?, ?, ?)",
(name, age, email)
)
conn.commit()
print("插入成功,用戶 ID:", cursor.lastrowid)
except sqlite3.Error as e:
conn.rollback()
print("插入失?。?, e)
finally:
conn.close()
def insert_many_users(users):
conn = get_connection()
cursor = conn.cursor()
try:
cursor.executemany(
"INSERT INTO users (name, age, email) VALUES (?, ?, ?)",
users
)
conn.commit()
print("批量插入成功")
except sqlite3.Error as e:
conn.rollback()
print("批量插入失?。?, e)
finally:
conn.close()
def query_all_users():
conn = get_connection()
cursor = conn.cursor()
cursor.execute("SELECT id, name, age, email, created_at FROM users")
rows = cursor.fetchall()
conn.close()
return [User(*row) for row in rows]
def query_user_by_id(user_id):
conn = get_connection()
cursor = conn.cursor()
cursor.execute(
"SELECT id, name, age, email, created_at FROM users WHERE id = ?",
(user_id,)
)
row = cursor.fetchone()
conn.close()
if row is None:
return None
return User(*row)
def update_user_age(user_id, new_age):
conn = get_connection()
cursor = conn.cursor()
cursor.execute(
"UPDATE users SET age = ? WHERE id = ?",
(new_age, user_id)
)
conn.commit()
if cursor.rowcount == 0:
print("沒(méi)有找到要修改的用戶")
else:
print("修改成功")
conn.close()
def delete_user(user_id):
conn = get_connection()
cursor = conn.cursor()
cursor.execute("DELETE FROM users WHERE id = ?", (user_id,))
conn.commit()
if cursor.rowcount == 0:
print("沒(méi)有找到要?jiǎng)h除的用戶")
else:
print("刪除成功")
conn.close()
def print_users(users):
for user in users:
print(
f"ID: {user.id}, 姓名: {user.name}, 年齡: {user.age}, "
f"郵箱: {user.email}, 創(chuàng)建時(shí)間: {user.created_at}"
)
if __name__ == "__main__":
create_table()
insert_user("張三", 22, "zhangsan@example.com")
insert_many_users([
("李四", 25, "lisi@example.com"),
("王五", 28, "wangwu@example.com"),
("趙六", 30, "zhaoliu@example.com")
])
print("\n查詢所有用戶:")
users = query_all_users()
print_users(users)
print("\n查詢 ID 為 1 的用戶:")
user = query_user_by_id(1)
print(user)
print("\n修改 ID 為 1 的用戶年齡:")
update_user_age(1, 23)
print("\n修改后的用戶列表:")
users = query_all_users()
print_users(users)
print("\n刪除 ID 為 2 的用戶:")
delete_user(2)
print("\n刪除后的用戶列表:")
users = query_all_users()
print_users(users)
十一、代碼運(yùn)行說(shuō)明
運(yùn)行代碼:
python sqlite_crud_demo.py
第一次運(yùn)行后,當(dāng)前目錄下會(huì)生成:
app.db
這個(gè)文件就是 SQLite 數(shù)據(jù)庫(kù)文件。
如果重復(fù)運(yùn)行示例代碼,可能會(huì)因?yàn)?email 字段設(shè)置了唯一約束而出現(xiàn)類(lèi)似錯(cuò)誤:
UNIQUE constraint failed: users.email
這是正?,F(xiàn)象,說(shuō)明同一個(gè)郵箱不能重復(fù)插入。測(cè)試時(shí)可以刪除 app.db 后重新運(yùn)行,或者修改示例中的郵箱地址。
十二、后端初學(xué)者需要掌握的重點(diǎn)
學(xué)習(xí) sqlite3 時(shí),建議重點(diǎn)掌握下面幾個(gè)點(diǎn):
- 數(shù)據(jù)庫(kù)連接:
sqlite3.connect() - 創(chuàng)建游標(biāo):
conn.cursor() - 執(zhí)行 SQL:
cursor.execute() - 參數(shù)化 SQL:使用
?占位符 - 提交事務(wù):
conn.commit() - 回滾事務(wù):
conn.rollback() - 關(guān)閉連接:
conn.close() - 查詢一條數(shù)據(jù):
fetchone() - 查詢多條數(shù)據(jù):
fetchall() - 判斷影響行數(shù):
cursor.rowcount
對(duì)于后端開(kāi)發(fā)來(lái)說(shuō),數(shù)據(jù)庫(kù)操作不僅僅是會(huì)寫(xiě) SQL,還要注意安全性和穩(wěn)定性。例如參數(shù)化 SQL 可以降低 SQL 注入風(fēng)險(xiǎn),事務(wù)處理可以避免數(shù)據(jù)寫(xiě)入一半就失敗的問(wèn)題。
十三、總結(jié)
本文通過(guò) Python 標(biāo)準(zhǔn)庫(kù) sqlite3 演示了本地 SQLite 數(shù)據(jù)庫(kù)的基本操作,包括:
- 創(chuàng)建數(shù)據(jù)庫(kù)
- 創(chuàng)建數(shù)據(jù)表
- 插入數(shù)據(jù)
- 查詢數(shù)據(jù)
- 修改數(shù)據(jù)
- 刪除數(shù)據(jù)
- 簡(jiǎn)單理解 ORM 思想
- 使用
dataclass把查詢結(jié)果轉(zhuǎn)換成 Python 對(duì)象 - 完整 CRUD 示例代碼
對(duì)于 Python 后端初學(xué)者來(lái)說(shuō),SQLite 是非常適合作為第一門(mén)數(shù)據(jù)庫(kù)實(shí)踐工具的。它不需要安裝數(shù)據(jù)庫(kù)服務(wù),只需要一個(gè) .db 文件就能完成完整的數(shù)據(jù)增刪改查。掌握這些基礎(chǔ)之后,再學(xué)習(xí) MySQL、PostgreSQL、SQLAlchemy 或 Django ORM,會(huì)更加順暢。
以上就是Python+sqlite3操作本地SQLite數(shù)據(jù)庫(kù)的實(shí)戰(zhàn)指南的詳細(xì)內(nèi)容,更多關(guān)于Python sqlite3操作SQLite數(shù)據(jù)庫(kù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
PyQT5 實(shí)現(xiàn)快捷鍵復(fù)制表格數(shù)據(jù)的方法示例
這篇文章主要介紹了PyQT5 實(shí)現(xiàn)快捷鍵復(fù)制表格數(shù)據(jù)的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
python3在各種服務(wù)器環(huán)境中安裝配置過(guò)程
這篇文章主要介紹了python3在各種服務(wù)器環(huán)境中安裝配置過(guò)程,源碼包編譯安裝步驟詳解,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-01-01
opencv3/Python 稠密光流calcOpticalFlowFarneback詳解
今天小編就為大家分享一篇opencv3/Python 稠密光流calcOpticalFlowFarneback詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
python 每天如何定時(shí)啟動(dòng)爬蟲(chóng)任務(wù)(實(shí)現(xiàn)方法分享)
python 每天如何定時(shí)啟動(dòng)爬蟲(chóng)任務(wù)?今天小編就為大家分享一篇python 實(shí)現(xiàn)每天定時(shí)啟動(dòng)爬蟲(chóng)任務(wù)的方法。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
Python+OpenCV實(shí)現(xiàn)邊緣檢測(cè)與角點(diǎn)檢測(cè)詳解
這篇文章主要為大家詳細(xì)介紹了如何通過(guò)Python+OpenCV實(shí)現(xiàn)邊緣檢測(cè)與角點(diǎn)檢測(cè),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Python與OpenCV有一定的幫助,需要的可以參考一下2023-02-02
對(duì)Python函數(shù)設(shè)計(jì)規(guī)范詳解
今天小編就為大家分享一篇對(duì)Python函數(shù)設(shè)計(jì)規(guī)范詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
python中property屬性的介紹及其應(yīng)用詳解
這篇文章主要介紹了python中property屬性的介紹及其應(yīng)用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
scrapy與selenium結(jié)合爬取數(shù)據(jù)(爬取動(dòng)態(tài)網(wǎng)站)的示例代碼
這篇文章主要介紹了scrapy與selenium結(jié)合爬取數(shù)據(jù)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09

