在SQLi中获取(从另一个表)时插入行

2024-06-08 17:46:41 发布

您现在位置:Python中文网/ 问答频道 /正文

不管python和sqlite如何,我都会遇到这个错误。在

  File "addbooks.py", line 77, in saveBook
  conn.commit()
  sqlite3.OperationalError: cannot commit transaction - SQL statements in progress

代码如下:

^{pr2}$

无法执行fetchall(),因为表和列的大小很大,而且内存不足。在

如果不使用肮脏的技巧(比如在内存中获取rowid,这很可能适合,然后逐个选择行)可以做什么呢?。在


Tags: inpysqlitesql错误lineconnsqlite3
3条回答

问题是您将连接置于自动提交模式。将一个事务包装在整个事务中,这样只有在完成所有更新之后才会进行提交,而且它应该都可以正常工作。在

问题是,对于一个连接,活动游标不应该超过一个。在

解决方案是使用新的连接进行更新。在

不幸的是,我不记得我在文件中读到它的确切位置,所以我无法证明它。在

升级版

以下代码适用于我的Windows XP:

import sqlite3
import os
conn1 = sqlite3.connect('test.db')
cursor1 = conn1.cursor()
conn2 = sqlite3.connect('test.db')
cursor2 = conn2.cursor()


cursor1.execute("CREATE TABLE my_table (a INT, b TEXT)")
cursor1.executemany("INSERT INTO my_table (a, b) VALUES (?, NULL);", zip(range(5)))
conn1.commit()

cursor1.execute("SELECT * FROM my_table")
for a, b in cursor1:
    cursor2.execute("UPDATE my_table SET b='updated' WHERE a = ?", (a, ))

conn2.commit()

print "results:"
print 10 * '-'
cursor1.execute("SELECT * FROM my_table")
for a, b in cursor1:
    print a, b
cursor1.close()
conn1.close()
cursor2.close()
conn2.close()
os.unlink('test.db')

并按预期返回以下内容:

^{pr2}$

如果我将conn2.commit()移到for循环中,就会得到与您提到的相同的错误:

Traceback (most recent call last):
  File "concurent.py", line 16, in <module>
    conn2.commit()
sqlite3.OperationalError: database is locked

因此,解决方案是在末尾提交一次,而不是在每行之后提交。在

不知道这是否也算作“肮脏的把戏”;—)

我对这个问题的解决方案是使用SELECT... LIMIT clause,假设您有主键整型字段id

current_id = 0
while True:    
    cread.execute('''select book_text from table where id > %s limit 2''' % current_id)
    results = cread.fetchall()
    if results is None:
        break;
    for row in results:
         ... (save book) ...
         current_id = row.id

相关问题 更多 >