所以我有一个大型数据库,我无法立即在内存中保存.我必须遍历表中的每个项目,处理它,并将处理后的数据放入表中的另一列.
当我循环我的光标时,如果我尝试运行更新语句,它会截断记录集(我相信因为它重新定位了游标对象).
问题:
创建第二个游标对象以运行更新语句是否允许我继续循环原始的select语句?
我是否需要与数据库建立第二个连接才能拥有第二个游标对象,这样我才能这样做?
sqlite如何响应与数据库的两个连接,一个从表中读取,另一个写入它?
我的代码(简化):
import sqlite3 class DataManager(): """ Manages database (used below). I cut this class way down to avoid confusion in the question. """ def __init__(self, db_path): self.connection = sqlite3.connect(db_path) self.connection.text_factory = str self.cursor = self.connection.cursor() def genRecordset(self, str_sql, subs=tuple()): """ Generate records as tuples, for str_sql. """ self.cursor.execute(str_sql, subs) for row in self.cursor: yield row select = """ SELECT id, unprocessed_content FROM data_table WHERE processed_content IS NULL """ update = """ UPDATE data_table SET processed_content = ? WHERE id = ? """ data_manager = DataManager(r'C:\myDatabase.db') subs = [] for row in data_manager.genRecordset(str_sql): id, unprocessed_content = row processed_content = processContent(unprocessed_content) subs.append((processed_content, id)) #every n records update the database (whenever I run out of memory) if len(subs) >= 1000: data_manager.cursor.executemany(update, subs) data_manager.connection.commit() subs = [] #update remaining records if subs: data_manager.cursor.executemany(update, subs) data_manager.connection.commit()
我尝试的另一种方法是将我的select语句修改为:
select = """ SELECT id, unprocessed_content FROM data_table WHERE processed_content IS NULL LIMIT 1000 """
然后我会这样做:
recordset = data_manager.cursor.execute(select) while recordset: #do update stuff... recordset = data_manager.cursor.execute(select)
我遇到的问题是我的真正的 select语句中有一个JOIN并且需要一段时间,因此多次执行JOIN非常耗费时间.我试图通过仅执行一次选择来加速该过程,然后使用生成器,因此我不必将其全部保存在内存中.
解:
好的,所以前两个问题的答案是"不".对于我的第三个问题,一旦与数据库建立连接,它就会锁定整个数据库,因此在第一个连接关闭之前,另一个连接将无法执行任何操作.
我找不到它的源代码,但从经验证据来看,我认为连接一次只能使用一个游标对象,最后一次运行查询优先.这意味着,当我循环选择的记录集时,一次产生一行,一旦我运行第一个更新语句,我的生成器就会停止产生行.
我的解决方案是创建一个临时数据库,我使用id粘贴processed_content,这样我每个数据库都有一个连接/游标对象,并且可以继续循环选定的记录集,同时定期插入临时数据库.一旦我到达所选记录集的末尾,我将临时数据库中的数据传回原始数据库.
如果有人确切知道连接/光标对象,请在评论中告诉我.