2015-08-20 2 views
2

Я пробовал читать источник pyobbc, но это все код C++ (я не компетентен в C++). Мне нужно знать поведение заявления, как:Если я использую диспетчер контекста с курсором pyobbc, он откатится от ошибки?

with connection.cursor() as cursor: 
    cursor.execute(query_1) #inserts some stuff into table A 
    cursor.execute(query_2) #inserts some stuff into table B, but throws an error 

with connection.cursor() as cursor2: 
    cursor.execute(select_query_1) #selects from table A 
    cursor.execute(select_query_2) #selects from table B 

Это в той же связи, где мы еще не совершил - Мне любопытно ли выбрать из таблицы А даст новые значения, вставленные в первом курсор - или вызывает ли ошибка в query_2 работу первого курсора откатить для таблицы А.

ответ

3

Глядя на source и ODBC Documentation поведения зависит, в частности, от того, autocommit включен или отключен ,

  • Первый вызов cursor.execute() неявно открывает новую транзакцию, если autocommit является False. (См. Примечание 1). Каждый последующий вызов execute() для этого курсора использует ту же транзакцию, если не вызваны commit() или rollback().
  • Когда Python покидает with блок и вызывает __exit__:
    • если autocommit является False, и не было никаких ошибок, курсор автоматически фиксирует транзакцию. См. Примечание 2 для источника этой операции.
    • если autocommit - True, или если есть ошибка, курсор выходит без завершения транзакции.
  • Когда курсор закрыт, либо с cursor.close() или когда __del__ явно или неявно называется, в ожидании результатов заявлении также автоматически удаляются, когда внутренняя ручка курсора освобождается. (Примечание 3)

Если cursor.execute() не удалось выполнить транзакцию, транзакция по-прежнему открыта, но не совершена. Это зависит от вас, чтобы совершить или откат в этом случае.

Все, что сказано, вы все равно должны проверить поведение в целевой среде. Различные источники данных ODBC имеют различные уровни поддержки транзакций.


Примечание 1: (source)

Если источник данных находится в ручном фиксации режима (требующий явного инициирования транзакции) и транзакции еще не был инициирован, водитель инициирует транзакцию прежде чем он отправит инструкцию SQL.

Примечание 2: (pyodbc/cursor.cpp @ 2151)

// If an error has occurred, `args` will be a tuple of 3 values. 
// Otherwise it will be a tuple of 3 `None`s. 
I(PyTuple_Check(args)); 
if (cursor->cnxn->nAutoCommit == SQL_AUTOCOMMIT_OFF && PyTuple_GetItem(args, 0) == Py_None) 
    ... 
    ret = SQLEndTran(SQL_HANDLE_DBC, cursor->cnxn->hdbc, SQL_COMMIT); 

Примечание 3: (source

Когда приложение вызывает SQLFreeHandle освободить заявление, которое ожидающий результаты, ожидающие результаты будут удалены.

0

pyodbc не обрабатывает транзакции автоматически.

Это означает, что select_query_1 увидит записи, вставленные query_1, даже если query_2 не удалось. (Я предполагаю try/catch вокруг первого блока кода, так что второй будет выполнен). Однако некоторые СУБД, а именно PostgreSQL, не позволяют выполнять какой-либо другой оператор (кроме откат), если один из предыдущих операторов в одной транзакции терпит неудачу. В случае RDBMS PostrgreSQL (например) и без autocommit, select_query_1 просто терпит неудачу, если запрос_2 не удался.

 Смежные вопросы

  • Нет связанных вопросов^_^