Непоследовательное поведение курсора sqlite при изменении базовой базы данных - PullRequest
0 голосов
/ 01 марта 2019

У меня проблемы с пониманием поведения объекта курсора модуля sqlite3 в python.Насколько я понимаю, объект-курсор ведет себя как итератор, сохраняющий «представление» о структуре данных.Теперь, я думаю, есть два способа, как это ведет себя:

1) при выполнении, состояние базы данных, соответствующее оператору SELECT *, остается отделенным от изменений фьючерсов

2) при выполнениисостояние базы данных, соответствующее оператору SELECT *, является просто представлением базовых изменяемых данных.Т.е. ленивая оценка выполняется после выполнения строки for ... in cur.

Но, очевидно, это не так, см. Сценарий и вывод ниже.Почему при выполнении этого скрипта команда UPDATE не включена в курсор, а INSERT есть?Лучше просто всегда использовать result = list(cur.execute(...))?

#!/usr/bin/env python3
import sqlite3

con = sqlite3.connect("db.sqlite")
con.execute("""CREATE TABLE IF NOT EXISTS `table` (
    `id`    INTEGER UNIQUE,
    `name`  TEXT,
    PRIMARY KEY(`id`)
);""")
con.execute("INSERT INTO `table` VALUES (1, 'smith')")
con.execute("INSERT INTO `table` VALUES (2, 'mia')")
con.commit()
print("in db: (1, smith), (2, mia)")

### Querying the table
cur = con.cursor()
cur.execute("SELECT * FROM `table`")

### Changing the table
print("altering table: add (3, kim), change (1, smith) to (1, james)")
con.execute("UPDATE `table` SET name='james' where id=1")
con.execute("INSERT INTO `table` VALUES (3, 'kim')")
con.commit()

print()
print("1) expect immutable: (1, smith), (2, mia)")
print("2) expect mutable: (1, james), (2, mia), (3, kim)")
print()
print("But got: ")
for row in cur: print(row)

Выход

in db: (1, smith), (2, mia)
altering table: add (3, kim), change (1, smith) to (1, james)

1) expect immutable: (1, smith), (2, mia)
2) expect mutable: (1, james), (2, mia), (3, kim)

But got: 
(1, 'smith')
(2, 'mia')
(3, 'kim')

Платформа

  • Ubuntu 18.10 x64
  • Python 3.6.7 (по умолчанию, 22 октября 2018 г., 11:32:17)
  • sqlite3.version = '2.6.0'

1 Ответ

0 голосов
/ 01 марта 2019

К сожалению, так работает SQLite.From Изоляция в SQLite :

... Но как быть с изменениями, которые происходят во время выполнения оператора SELECT?Что, если оператор SELECT запущен, а интерфейс sqlite3_step () проходит примерно половину своего вывода, тогда некоторые операторы UPDATE выполняются приложением, которое изменяет таблицу, которую читает оператор SELECT, а затем выполняется больше вызовов sqlite3_step ()закончить оператор SELECT?Увидят ли последующие шаги оператора SELECT изменения, сделанные UPDATE, или нет?Ответ заключается в том, что это поведение не определено ... И, следовательно, разработчики должны старательно избегать написания приложений, которые делают предположения о том, что произойдет в этих обстоятельствах.

Это означает, что SQLite может обеспечить некоторую изоляцию между различнымисоединения с одной и той же базой данных (будьте осторожны, должен писать только один), но вы не должны пытаться изменять базу данных, по крайней мере, таблицы, которые читаются, между началом и концом SELECT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...