1. Python3连接SQLite3的完整指南
SQLite作为轻量级数据库引擎,在Python生态中有着广泛的应用场景。无论是开发原型系统、移动应用还是嵌入式设备,SQLite3模块都是Python开发者不可或缺的工具。本文将深入讲解Python3操作SQLite3的完整流程,包含连接管理、CRUD操作、事务控制等核心知识点。
1.1 环境准备与基础连接
Python标准库已内置sqlite3模块,无需额外安装。建立数据库连接是最基础的操作:
import sqlite3
# 创建内存数据库(临时)
conn = sqlite3.connect(':memory:')
# 创建/连接磁盘数据库文件
conn = sqlite3.connect('example.db')
# 使用with语句自动管理连接
with sqlite3.connect('example.db') as conn:
pass # 数据库操作代码
连接参数说明:
-
:memory:表示创建内存数据库,程序退出后数据消失 - 文件路径则创建持久化数据库,若文件不存在会自动创建
- 推荐使用with语句管理连接,可自动处理连接的关闭
注意:SQLite是服务器进程的数据库引擎,所有操作都在本地完成。连接对象是线程不安全的,多线程环境需要为每个线程创建独立连接。
1.2 连接参数详解
connect()方法支持多个可选参数:
conn = sqlite3.connect(
'example.db',
timeout=5.0, # 等待锁的超时时间(秒)
detect_types=sqlite3.PARSE_DECLTYPES, # 类型检测模式
isolation_level=None, # 事务隔离级别
check_same_thread=True # 是否检查线程安全
)
关键参数解析:
-
timeout:当多个连接访问同一数据库时的等待超时 -
detect_types:启用类型转换(PARSE_DECLTYPES/PARSE_COLNAMES) -
isolation_level:控制事务行为(None/"DEFERRED"/"IMMEDIATE"/"EXCLUSIVE")
2. 基本CRUD操作
2.1 创建表与插入数据
通过Cursor对象执行SQL语句:
# 获取游标对象
cursor = conn.cursor()
# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
# 插入单条数据(安全的方式)
cursor.execute(
'INSERT INTO users (name, age) VALUES (?, ?)',
('Alice', 25)
)
# 插入多条数据
users = [
('Bob', 30),
('Charlie', 35),
('David', 40)
]
cursor.executemany(
'INSERT INTO users (name, age) VALUES (?, ?)',
users
)
# 提交事务
conn.commit()
重要:始终使用参数化查询(?占位符)而非字符串拼接,可防止SQL注入攻击。
2.2 查询与结果处理
查询结果可以通过多种方式获取:
# 查询所有记录
cursor.execute('SELECT * FROM users')
all_rows = cursor.fetchall() # 获取全部结果
# 逐行获取
cursor.execute('SELECT * FROM users')
for row in cursor:
print(row)
# 获取单条记录
cursor.execute('SELECT * FROM users WHERE id = ?', (1,))
user = cursor.fetchone()
# 使用字典形式返回结果
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute('SELECT * FROM users WHERE id = ?', (1,))
user = cursor.fetchone()
print(user['name']) # 通过列名访问
结果处理技巧:
-
fetchall():返回所有行的列表 -
fetchone():返回下一行 -
fetchmany(size):返回指定数量的行 -
设置
row_factory可改变返回结果的格式
2.3 更新与删除操作
更新和删除操作同样使用execute方法:
# 更新数据
cursor.execute(
'UPDATE users SET age = ? WHERE name = ?',
(26, 'Alice')
)
# 删除数据
cursor.execute(
'DELETE FROM users WHERE id = ?',
(5,)
)
# 获取受影响的行数
print(f"Rows affected: {cursor.rowcount}")
conn.commit()
3. 高级特性与应用
3.1 事务控制
SQLite支持完整的事务特性:
try:
# 开始事务(默认自动开始)
cursor.execute("BEGIN")
# 执行多个操作
cursor.execute("INSERT INTO users (name) VALUES ('Eve')")
cursor.execute("UPDATE users SET age = 20 WHERE name = 'Eve'")
# 提交事务
conn.commit()
except Exception as e:
# 出错时回滚
conn.rollback()
print(f"Transaction failed: {e}")
事务模式说明:
-
isolation_level=None:自动提交模式(非标准) -
isolation_level="DEFERRED":延迟锁获取(默认) -
isolation_level="IMMEDIATE":立即获取保留锁 -
isolation_level="EXCLUSIVE":获取独占锁
3.2 自定义函数与聚合
可以在SQL中注册Python函数:
# 注册标量函数
def reverse_string(s):
return s[::-1]
conn.create_function("reverse", 1, reverse_string)
# 在SQL中使用
cursor.execute("SELECT reverse(name) FROM users")
print(cursor.fetchall())
# 注册聚合函数
class Average:
def __init__(self):
self.sum = 0
self.count = 0
def step(self, value):
self.sum += value
self.count += 1
def finalize(self):
return self.sum / self.count if self.count else 0
conn.create_aggregate("avg_py", 1, Average)
cursor.execute("SELECT avg_py(age) FROM users")
print(cursor.fetchone()[0])
3.3 类型适配与转换
处理非标准数据类型:
import datetime
# 适配Python日期到SQLite
def adapt_date(date):
return date.isoformat()
sqlite3.register_adapter(datetime.date, adapt_date)
# 转换SQLite值到Python日期
def convert_date(s):
return datetime.date.fromisoformat(s.decode())
sqlite3.register_converter("DATE", convert_date)
# 使用类型检测
conn = sqlite3.connect(
'example.db',
detect_types=sqlite3.PARSE_DECLTYPES
)
cursor.execute('''
CREATE TABLE events (
id INTEGER PRIMARY KEY,
name TEXT,
event_date DATE
)
''')
today = datetime.date.today()
cursor.execute(
'INSERT INTO events (name, event_date) VALUES (?, ?)',
('Conference', today)
)
cursor.execute('SELECT event_date FROM events')
event = cursor.fetchone()
print(type(event[0])) # <class 'datetime.date'>
4. 性能优化与最佳实践
4.1 批量操作优化
大量数据插入时使用特殊技巧:
# 1. 使用executemany(中等规模数据)
data = [(f'User_{i}', i) for i in range(1000)]
cursor.executemany(
'INSERT INTO users (name, age) VALUES (?, ?)',
data
)
# 2. 显式事务(大数据量)
conn.execute("BEGIN")
try:
for i in range(10000):
cursor.execute(
'INSERT INTO users (name, age) VALUES (?, ?)',
(f'User_{i}', i)
)
conn.commit()
except:
conn.rollback()
raise
# 3. 使用备份API(超大数据量)
conn.execute("CREATE TABLE big_data (id INTEGER, data TEXT)")
conn.execute("BEGIN")
for i in range(100000):
if i % 1000 == 0:
conn.commit()
conn.execute("BEGIN")
conn.execute(
"INSERT INTO big_data VALUES (?, ?)",
(i, 'x'*100)
)
conn.commit()
4.2 索引与查询优化
# 创建索引
cursor.execute('CREATE INDEX idx_users_age ON users(age)')
# 分析查询计划
cursor.execute('EXPLAIN QUERY PLAN SELECT * FROM users WHERE age > 30')
print(cursor.fetchall())
# 使用覆盖索引
cursor.execute('CREATE INDEX idx_users_covering ON users(name, age)')
cursor.execute('SELECT name, age FROM users WHERE age BETWEEN 20 AND 30')
4.3 常见问题排查
-
数据库锁定问题 :
-
错误:
sqlite3.OperationalError: database is locked - 解决方案:增加timeout参数,优化事务范围
-
错误:
- 类型转换错误 :
-
错误:
sqlite3.InterfaceError: Error binding parameter - 检查:确保参数类型与字段类型匹配
- 内存管理 :
- 对于大型查询,使用迭代而非fetchall:
cursor.execute('SELECT * FROM large_table')
for row in cursor:
process(row) # 逐行处理,避免内存爆炸
-
连接泄漏 :
- 始终确保连接被关闭:
# 正确做法
with sqlite3.connect('db.sqlite') as conn:
# 操作代码
# 或者显式关闭
try:
conn = sqlite3.connect('db.sqlite')
# 操作代码
finally:
conn.close()
5. 实际应用案例
5.1 Web应用中的使用
from flask import Flask, g
app = Flask(__name__)
def get_db():
if 'db' not in g:
g.db = sqlite3.connect('app.db')
g.db.row_factory = sqlite3.Row
return g.db
@app.teardown_appcontext
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
@app.route('/users')
def list_users():
db = get_db()
users = db.execute('SELECT * FROM users').fetchall()
return {'users': [dict(user) for user in users]}
5.2 数据分析应用
import sqlite3
import pandas as pd
# 将SQLite数据加载到Pandas
with sqlite3.connect('data.db') as conn:
df = pd.read_sql('SELECT * FROM sales', conn)
# 使用Pandas分析后写回SQLite
with sqlite3.connect('report.db') as conn:
df.groupby('category').sum().to_sql(
'sales_summary',
conn,
if_exists='replace'
)
5.3 嵌入式设备应用
# 在树莓派等设备上的典型用法
import sqlite3
from sensors import read_temperature
DB_PATH = '/mnt/sd_card/data.db'
def init_db():
conn = sqlite3.connect(DB_PATH)
conn.execute('''
CREATE TABLE IF NOT EXISTS readings (
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
value REAL
)
''')
conn.commit()
conn.close()
def log_reading(value):
conn = sqlite3.connect(DB_PATH)
conn.execute('INSERT INTO readings (value) VALUES (?)', (value,))
conn.commit()
conn.close()
# 定时记录传感器数据
init_db()
while True:
temp = read_temperature()
log_reading(temp)
time.sleep(60)
6. 安全注意事项
-
SQL注入防护 :
- 永远不要使用字符串拼接构造SQL
- 始终使用参数化查询:
# 危险!
cursor.execute(f"SELECT * FROM users WHERE name = '{user_input}'")
# 安全
cursor.execute("SELECT * FROM users WHERE name = ?", (user_input,))
-
数据验证 :
- 对所有输入数据进行验证和清理
- 使用白名单验证复杂输入
-
敏感数据保护 :
- SQLite不提供内置加密(社区版本)
- 对敏感数据考虑应用层加密
- 使用SQLCipher等加密版本处理敏感数据
- 备份策略 :
# 简单备份方法
def backup_db(src_path, dst_path):
src = sqlite3.connect(src_path)
dst = sqlite3.connect(dst_path)
with dst:
src.backup(dst)
src.close()
dst.close()
在实际项目中,根据具体需求选择合适的SQLite使用模式。对于简单的数据存储需求,直接使用Python标准库的sqlite3模块即可;对于复杂应用,可以考虑结合SQLAlchemy等ORM工具使用。













