新しい行を挿入し、途中で既存の行を更新しながら、テーブル内の多くの (1,000,000 +) 行を反復処理するアプリケーションを開発しています。select ステートメントは、テーブル内のすべての行 (select が最初に実行されたときに存在する行) を 1 回だけ生成し、select の実行後に挿入された行を決して生成しないことが要件です。すべての行をメモリにロードするのは避けたいと思います (これには長い時間と大量の RAM が必要です。試してみました)。
私は、SQLite が実行時間の長い選択から挿入 (およびおそらく更新と削除) を分離しないように見えることを示す小さな Python の例を開発しました。この動作について具体的に言及している SQLite ドキュメントの場所を見つけることができませんでしたが、(おそらく SQLite の以前のバージョンでは?) 挿入が失敗するという事実をほのめかしているいくつかのリンクを見つけましたが、私の例ではそうではありません。 .
import sqlite3
def select_affected_by_insert():
# select from and simultaneously modify same table
cn = sqlite3.connect(':memory:')
cn.execute("CREATE TABLE demo (v INTEGER PRIMARY KEY)")
n = 5
values = [[v] for v in range(n)]
cn.executemany('INSERT INTO demo VALUES (?)', values)
for (v,) in cn.execute('SELECT v FROM demo'):
with cn:
# insert in transaction
cn.execute('INSERT INTO demo VALUES (?)', [n + v])
print v, n + v
assert v < n, 'got more rows than expected!'
if __name__ == '__main__':
select_affected_by_insert()
SQLite 3.6.12
パイソン 2.6.4
データを別の (一時) テーブルにコピーしてそこから選択するよりも、これを回避するより良い方法はありますか?
明確化: ループ内でコミットを行う必要があることを言い忘れていました。プロセスは中断される可能性があり、部分的に完了した作業はコミットする必要があるため、次の実行時にやり直す必要はありません。