2010-05-16 51 views
3

無論使用python還是sqlite,我都會收到此錯誤。在SQLite中讀取(從另一個表中)時插入行

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

的代碼看起來是這樣的:

conn = sqlite3.connect(fname) 
cread = conn.cursor() 

cread.execute('''select book_text from table''') 
while True: 
    row = cread.fetchone() 
    if row is None: 
     break 
    .... 
    for entry in getEntries(doc): 
     saveBook(entry, conn) 

不能做一個使用fetchall(),因爲表和列的尺寸是大的,而內存不足。

沒有訴諸骯髒的技巧可以做什麼(如獲取內存中的rowid,這可能適合,然後逐一選擇行)?

回答

1

不知道這樣算不算「搞鬼」太;-)

我對這個問題的解決方案是使用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 
+0

是的,這有點棘手......它可能工作,雖然:-) – Samuel 2010-05-16 19:42:42

2

的問題在於您已將連接保留爲自動提交模式。在整個過程中包裝單個事務,以便在完成所有更新後纔會發生提交,並且它應該都可以正常工作。

+0

連接不是在自動提交模式下,我試圖明確設置isolation_level,併發生同樣的情況。在處理結束時進行單次提交不是一種選擇,因爲saveBook中存在「部分回滾」,只應回滾一些更改,而不是完成整個工作(可能不允許我提交,讓我「回滾」) – Samuel 2010-05-16 19:40:48

+0

@Samuel:你可以嘗試使用[SAVEPOINT](http://www.sqlite.org/lang_savepoint.html),我認爲*是一種中途檢查點...但我警告說,我從來沒有嘗試過,所以我只知道我讀過的關於它們的一點點。 – 2010-05-16 21:07:28

0

問題是連接中應該只有一個活動遊標。

解決方案是使用新的連接進行更新。

不幸的是我不記得在我看過的文檔中的確切位置,所以我不能證明它。

UPD

下面的代碼工作在我的Windows XP:

results: 
---------- 
0 updated 
1 updated 
2 updated 
3 updated 
4 updated 

如果我移動conn2.commit()到了:

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') 

,並返回預期以下循環,我得到了你提到的同樣的錯誤:

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

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

+0

我也試過,但得到「數據庫被鎖定」的錯誤之類的。無論如何,我採取了駭人的解決方案,並繼續前進。 – Samuel 2010-05-24 16:17:51

+0

@Samuel:我用一個例子更新了我的答案。 – newtover 2010-05-24 17:26:35

相關問題