diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index d317ead66f9bcb..123f18e822100e 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -243,6 +243,7 @@ inserted data and retrieved values from it in multiple ways. * :ref:`sqlite3-converters` * :ref:`sqlite3-connection-context-manager` * :ref:`sqlite3-howto-row-factory` + * :ref:`sqlite3-howto-pragma-in-transaction` * :ref:`sqlite3-explanation` for in-depth background on transaction control. @@ -1353,8 +1354,6 @@ Connection objects implying that :mod:`!sqlite3` ensures a transaction is always open. Use :meth:`commit` and :meth:`rollback` to close transactions. - This is the recommended value of :attr:`!autocommit`. - * ``True``: Use SQLite's `autocommit mode`_. :meth:`commit` and :meth:`rollback` have no effect in this mode. @@ -1367,7 +1366,10 @@ Connection objects Changing :attr:`!autocommit` to ``False`` will open a new transaction, and changing it to ``True`` will commit any pending transaction. - See :ref:`sqlite3-transaction-control-autocommit` for more details. + .. seealso:: + + * :ref:`sqlite3-transaction-control-autocommit` + * :ref:`sqlite3-howto-pragma-in-transaction` .. note:: @@ -2429,6 +2431,39 @@ the context manager does nothing. couldn't add Python twice +.. _sqlite3-howto-pragma-in-transaction: + +How to use ``PRAGMA`` statements with implicit transaction control +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some ``PRAGMA`` statements have no effect within transactions. +For example, a ``PRAGMA foreign_keys=ON`` query will silently fail +if there is an open transaction. +In order to safely use ``PRAGMA`` statements, +ensure that there is no open transaction: + +* If :attr:`~Connection.autocommit` is ``True`` + and a transaction was explicitly opened, + make sure to :meth:`~Cursor.execute` a ``COMMIT`` + before executing the ``PRAGMA`` statement. +* Else, temporarily disable implicit transaction control + using the :attr:`!autocommit` attribute + before executing the ``PRAGMA`` statement: + + .. testcode:: + :hide: + + con = sqlite3.connect(":memory:", autocommit=False) + + .. testcode:: + + cur = con.cursor() + saved = con.autocommit + con.autocommit = True # Disable implicit transaction control. + cur.execute("PRAGMA foreign_keys=ON") + con.autocommit = saved # Restore the previous setting. + + .. _sqlite3-uri-tricks: How to work with SQLite URIs @@ -2643,11 +2678,9 @@ Transaction control via the ``autocommit`` attribute The recommended way of controlling transaction behaviour is through the :attr:`Connection.autocommit` attribute, -which should preferably be set using the *autocommit* parameter -of :func:`connect`. +normally set using the *autocommit* parameter of :func:`connect`. -It is suggested to set *autocommit* to ``False``, -which implies :pep:`249`-compliant transaction control. +Set *autocommit* to ``False`` for :pep:`249`-compliant transaction control. This means: * :mod:`!sqlite3` ensures that a transaction is always open, @@ -2660,6 +2693,16 @@ This means: * An implicit rollback is performed if the database is :meth:`~Connection.close`-ed with pending changes. +.. note:: + + Some ``PRAGMA`` statements have no effect when a transaction is open. + If ``PRAGMA`` statements are a part of the database connection setup + and you want :pep:`249`-compliant transaction control, + set *autocommit* to ``True`` in :func:`connect`, + execute the needed ``PRAGMA`` statements, + then set :attr:`Connection.autocommit` to ``False``. + See :ref:`sqlite3-howto-pragma-in-transaction` for details. + Set *autocommit* to ``True`` to enable SQLite's `autocommit mode`_. In this mode, :meth:`Connection.commit` and :meth:`Connection.rollback` have no effect. @@ -2716,6 +2759,11 @@ The :meth:`~Cursor.executescript` method implicitly commits any pending transaction before execution of the given SQL script, regardless of the value of :attr:`~Connection.isolation_level`. +.. note:: + + Some ``PRAGMA`` statements cannot be set when a transaction is open. + See :ref:`sqlite3-howto-pragma-in-transaction` for details. + .. versionchanged:: 3.6 :mod:`!sqlite3` used to implicitly commit an open transaction before DDL statements. This is no longer the case.