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

