Python sqlite3内存临时数据库作用及fetchall返回空列表原因解析
你提供的SQLite操作代码格式化后如下:
import sqlite3 conn = sqlite3.connect(":memory:") cur = conn.cursor() cur.executescript(""" create table person( firstname, lastname, age ); create table book( title, author, published ); insert into book(title, author, published) values ( 'Dirk Gently''s Holistic Detective Agency', 'Douglas Adams', 1987 ); """) cur.execute(""" SELECT * FROM book """) print(conn) conn.commit() x=cur.fetchall() print(x)
问题1::memory:参数的含义
你的猜测完全正确,给sqlite3.connect传入:memory:参数时,SQLite不会在磁盘上创建数据库文件,而是直接在当前进程的RAM内存中创建一个临时数据库,一旦数据库连接关闭或者程序运行结束,这个数据库的所有数据就会被直接销毁,不会留下任何痕迹。
问题2:fetchall()返回空列表的原因
问题出在代码的执行顺序:
你在执行cur.execute("SELECT * FROM book")之后,没有立刻从游标中读取结果,而是先调用了conn.commit()提交事务。SQLite中事务提交后,当前连接上所有未读取的游标结果集会被直接清空,所以后续调用fetchall()就只能拿到空列表。
只需要调整顺序即可解决:执行SELECT查询后先调用fetchall()取数,再执行commit操作。
问题3:内存临时数据库的使用场景
- 单元测试:测试数据库操作逻辑时不用创建物理文件,测试结束自动销毁数据,不需要额外清理测试垃圾
- 临时数据处理:做数据清洗、临时统计计算等不需要持久化存储的操作,内存读写性能远高于磁盘
- 敏感数据处理:处理涉密、敏感数据时,使用内存库不会在磁盘留下任何数据残留,安全性更高
- 快速原型开发:调试SQL逻辑、快速验证功能时不用管理数据库文件,随用随建
- 高频临时缓存:作为临时缓存存储高频率读写的热数据,降低磁盘IO开销
问题4:execute和executescript的区别及注意事项
核心区别
execute一次只能执行单条SQL语句,支持参数绑定,执行查询类SQL后可以直接从游标获取结果,适合执行单条增删改查操作executescript可以一次性执行多条用分号分隔的SQL语句,执行前会隐式提交当前未完成的事务,不会返回单条SQL的执行结果,适合批量执行建表、初始化数据这类批量SQL脚本
executescript注意事项
- 执行前会自动提交之前未提交的事务,所以之前的未提交操作无法回滚
- 无法获取脚本中单条查询语句的返回结果,不要用它执行需要拿返回值的查询SQL
- 如果脚本中拼接了用户可控的输入内容,SQL注入风险远高于单条
execute,要严格校验输入内容,尽量避免拼接用户输入 - 脚本中任意一条SQL出现语法错误,后续的SQL都会终止执行,如果需要保证原子性,建议在脚本开头手动加
BEGIN TRANSACTION,结尾加COMMIT,避免出现部分执行成功的问题
内容的提问来源于stack exchange,提问作者Dilshan Madhuranga
相关产品推荐
相关产品推荐

