Python操作sqlite3时简单循环中丢失fetchAll返回值的原因是什么
问题原因
- SQLite的游标(cursor)对象的fetch系列方法存在指针移动特性:每调用一次
fetchone()/fetchall()/fetchmany(),游标就会向后移动对应行数,当游标移动到结果集末尾后,所有fetch调用都会返回None,你的代码触发了两个相关错误:
- 执行查询语句后你先调用了
cdb.fetchall(),该方法会一次性取出全部查询结果,调用完成后游标已经处于结果集末尾,后续所有cdb.fetchone()调用都会返回None,对None执行下标取值、方法调用都会抛出异常。 - 即使移除首次
fetchall()调用,你在循环内判断条件时调用了一次fetchone(),打印时又调用了一次fetchone(),会导致每次循环跳过一行,很快就会遍历到结果集末尾拿到None。
修复方案
你可以先把查询结果全部存入本地变量再遍历,避免反复操作游标:
import sqlite3 db=sqlite3.connect('db.db') cdb=db.cursor() cdb.execute('create table if not exists table1 (field1,field2,field3)') cdb.execute('insert into table1 values (?,?,?)',(1,2,3)) db.commit() cdb.execute('insert into table1 values (?,?,?)',(4,5,6)) db.commit() cdb.execute('insert into table1 values (?,?,?)',(1,7,8)) db.commit() cdb.execute('select * from table1') # 把结果集提前存到变量中 all_rows = cdb.fetchall() for row in all_rows: if row[0] == 1: print(row) db.close()
如果查询结果量很大,不想一次性加载到内存,也可以直接遍历游标对象:
# 替换上面的查询遍历逻辑即可 cdb.execute('select * from table1') for row in cdb: if row[0] == 1: print(row)
内容的提问来源于stack exchange,提问作者Tommy
相关产品推荐
相关产品推荐

