Я занимаюсь разработкой приложения, в котором я перебираю множество (более 1 000 000) строк в таблице, одновременно вставляя новые строки и обновляя существующие строки.Требуется, чтобы оператор select выдавал каждую строку в таблице (те, которые существуют при первоначальном выполнении выбора) ровно один раз и никогда не приводил к строкам, которые вставляются после выполнения выбора.Я бы предпочел не загружать все строки в память (это занимает много времени и много оперативной памяти - я попробовал это).
Я разработал небольшой пример Python, который демонстрирует, что SQLite, очевидно, не изолирует вставки (и предположительно обновляет и удаляет) из длительной выборки.Мне не удалось найти места в документации по 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.12Python 2.6.4
Есть ли лучший способ обойти это, чем копировать данные в отдельную (временную) таблицу и выбирать из нее?
Уточнение: я забыл сказать, что мне нужноделать коммиты внутри цикла.Процесс может быть прерван, и частично выполненная работа должна быть зафиксирована, чтобы ее не нужно было повторять при следующем прогоне.