在python-2.7的sqlite3中的嵌套循环中使用多个游标

tji*_*jim 15 python sqlite python-2.7

我在嵌套循环中的单个sqlite数据库上使用多个游标时遇到问题.我找到了一个适合我的解决方案,但它有限,我没有看到在线记录这个具体问题.我这样发布: - 一个明确的问题/解决方案可用 - 看看是否有更好的解决方案 - 也许我在sqlite3 python模块中发现了一个缺陷

情况就是这样:我的Python应用程序将社交关系数据存储在sqlite中.数据集包括两个表之间的一对多关系:myConnections和sharedConnections.前者每个连接都有一行.sharedConnections表具有0:N行,具体取决于共享的连接数.为了构建结构,我使用嵌套循环.在外部循环中,我访问myConnections中的每一行.在内部循环中,我填充sharedConnections表.代码如下所示:

curOuter = db.cursor()  
for row in curOuter.execute('SELECT * FROM myConnections'):    
    id  = row[0]  
    curInner = db.cursor()  
    scList = retrieve_shared_connections(id)  
    for sc in scList:  
        curInner.execute('''INSERT INTO sharedConnections(IdConnectedToMe, IdShared) VALUES (?,?)''', (id,sc))  
db.commit()  
Run Code Online (Sandbox Code Playgroud)

结果很奇怪.该sqlite3表获取前两个记录的重复条目sharedConnections.他们有点整理.A的连接,B的连接,然后是A,然后是B.在最初的口吃之后,处理是正确的!例:

myConnections
-------------
a   
b  
c  
d  

sharedConnections
-------------
a->b  
a->c  
b->c  
b->d  
a->b  
a->c  
b->c  
b->d  
Run Code Online (Sandbox Code Playgroud)

解决方案不完善.而不是使用迭代器从外循环光标,我myConnections,然后SELECT和遍历结果列表.由于我的数据集很小,这没关系.

curOuter = db.cursor()
curOuter.execute('SELECT * FROM myConnections'):
rows = curOuter.fetchall()
for row in rows:    
    id  = row[0]
    curInner = db.cursor()
    scList = retrieve_shared_connections(id)
    for sc in scList:
        curInner.execute('''INSERT INTO sharedConnections(IdConnectedToMe, IdShared) VALUES (?,?)''', (id,sc))
db.commit()
Run Code Online (Sandbox Code Playgroud)

你有它.在嵌套循环中对同一sqlite数据库中的不同表使用两个游标似乎不起作用.更重要的是,它不会失败,只会给出奇怪的结果.

所以: - 这真的是最好的解决方案吗?
- 有更好的解决方案吗?
- 这是一个应该解决的缺陷吗?

答案:此时,问题已经提出,有一些讨论,我认为我们已经完成了很多.这是看起来如何:

  1. 您无法使用python中的sqlite3模块在嵌套循环中可靠地使用多个游标.遗憾的是,我们没有得到明确的确认.
  2. 有一个比我发布的解决方案更好的解决方案.2a:将选择减少到你需要的字段(我正在使用*).2b:构造循环,使最小的占用空间进入内存.对于这种情况,sharedConnections <= connections(它是一个子集).因此,在连接上使用游标并在内存中累积sharedConnections.2c:在累积的sharedConnections列表上使用.executemany应该比内部循环上的.execute更有效.
  3. 这是一个缺陷吗?我们没有得到答案.我想这就是生活!

感谢大家的关注和建议.

最好的问候,-Jim

Mar*_*ers 5

看起来您遇到了问题 10513,已在 Python 2.7.13、3.5.3 和 3.6.0b1 中修复。

处理事务的方式存在错误,在某些情况下所有游标状态都被重置。这导致重新curOuter从头开始。

解决方法是升级,或者在您可以升级之前,不要跨事务提交使用游标。通过使用curOuter.fetchall()你实现了后者。


Ano*_*nov 2

您可以构建一个行列表以插入内部循环中,然后在循环外部插入cursor.executemany()。这并不能回答多光标问题,但可能是您的解决方法。

curOuter = db.cursor()
rows=[]
for row in curOuter.execute('SELECT * FROM myConnections'):    
    id  = row[0]    
    scList = retrieve_shared_connections(id)  
    for sc in scList:

        rows.append((id,sc))
curOuter.executemany('''INSERT INTO sharedConnections(IdConnectedToMe, IdShared) VALUES (?,?)''', rows)  
db.commit()
Run Code Online (Sandbox Code Playgroud)

最好只从 myConnections 中选择 ID:

curOuter.execute('SELECT id FROM myConnections')
Run Code Online (Sandbox Code Playgroud)