Looking at the source, and the ODBC Documentation the behavior depends, in part, on whether autocommit
is enabled, or disabled.
- The first call to
cursor.execute()
implicitly opens a new transaction, if autocommit
is False
. (See Note 1) Each subsequent call to execute()
for this cursor uses the same transaction, unless commit()
or rollback()
are called.
- When Python leaves the
with
block and calls __exit__
:
- if
autocommit
is False
, and there were no errors, the cursor automatically commits the transaction. See note 2 for the source of this operation.
- if
autocommit
is True
, or if there is an error, the cursor exits without ending the transaction.
- When the cursor is closed, either with
cursor.close()
or when __del__
is explicitly or implicitly called, pending statement results are also automatically deleted when the cursor's internal handle is freed. (Note 3)
If cursor.execute()
fails, the transaction is still open, but not committed. It is up to you to commit, or rollback in this case.
All that said, you should still test the behavior in your target environment. Different ODBC data sources have different levels of transaction support.
Note 1: (source)
If the data source is in manual-commit mode (requiring explicit transaction initiation) and a transaction has not already been initiated, the driver initiates a transaction before it sends the SQL statement.
Note 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);
Note 3: (source
When an application calls SQLFreeHandle to free a statement that has pending results, the pending results are deleted.