SQLite3足以支撑单机图书借阅系统,但需启用外键(PRAGMA foreign_keys=ON)、事务保护、合理主外键设计及DATE类型日期处理,否则易致数据不一致或并发错误。

SQLite3 足够支撑一个单机版图书借阅系统,无需额外安装数据库服务,但直接裸用 sqlite3 模块容易在事务、日期处理、外键约束和并发写入上出问题——尤其当多人模拟借还书时,COMMIT 忘记或 PRAGMA foreign_keys = ON 没开,会导致数据不一致。
建表前必须启用外键并设计合理主外键关系
SQLite 默认关闭外键约束,不手动开启会导致 FOREIGN KEY 定义形同虚设,删书时借阅记录不会级联清除,造成脏数据。
实操建议:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 连接后立即执行
conn.execute("PRAGMA foreign_keys = ON"),且每次新连接都要做 -
books表用isbn(TEXT)作主键比自增id更实用,避免重复录入同一本书 -
borrow_records表中book_isbn和user_id都应设为NOT NULL,并联合建唯一索引防止同一用户重复借同一本书未归还 - 示例建表语句片段:
CREATE TABLE books ( isbn TEXT PRIMARY KEY, title TEXT NOT NULL, author TEXT ); CREATE TABLE borrow_records ( id INTEGER PRIMARY KEY AUTOINCREMENT, book_isbn TEXT NOT NULL, user_id TEXT NOT NULL, borrow_date DATE DEFAULT (date('now')), return_date DATE, FOREIGN KEY (book_isbn) REFERENCES books(isbn) );借书和还书必须包裹在事务里,且检查业务逻辑前置条件
单纯
INSERT一条借阅记录不够:得先查书是否存在、是否已被借出、用户是否已借满(比如最多借3本)。这些判断和写入必须原子化,否则并发时可能超借。实操建议:
- 用
conn.execute("BEGIN EXCLUSIVE")启动独占事务,比默认的BEGIN DEFERRED更安全 - 借书前查
SELECT COUNT(*) FROM borrow_records WHERE user_id = ? AND return_date IS NULL,确认未超限 - 查书是否可借:
SELECT 1 FROM books WHERE isbn = ?且NOT EXISTS (SELECT 1 FROM borrow_records WHERE book_isbn = ? AND return_date IS NULL) - 所有检查通过后再
INSERT INTO borrow_records (book_isbn, user_id),最后conn.commit();任一环节失败则conn.rollback()
日期字段别用字符串存,用 SQLite 内置 date() 函数配合 Python datetime
很多人把
borrow_date设成 TEXT 存"2024-05-20",看似简单,但后续想查“近7天借书量”就得手写字符串截取,既慢又易错。实操建议:
- 建表时声明为
DATE类型(SQLite 实际仍存字符串,但约定用 ISO8601 格式) - Python 插入时传
datetime.date.today(),SQLite3 会自动转成"2024-05-20" - 查询时用 SQLite 的
date('now', '-7 days'):SELECT * FROM borrow_records WHERE borrow_date >= date('now', '-7 days') - 避免在 Python 层解析日期字符串,减少类型转换开销
最常被忽略的是连接复用和关闭时机:Web 场景下每个请求新建
sqlite3.connect()没问题,但桌面应用若长期持有连接又不设timeout,遇到写锁会卡死;另外conn.close()忘关不是内存泄漏,而是可能让 WAL 日志堆积无法清理。 - 用
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










