Ticket #9206: 9206-r9084-raw-sql-docs.diff

File 9206-r9084-raw-sql-docs.diff, 4.9 KB (added by Richard Davies <richard.davies@…>, 7 years ago)

Improve documentation on raw SQL queries

  • docs/topics/db/models.txt

     
    725725--------------------
    726726
    727727Another common pattern is writing custom SQL statements in model methods and
    728 module-level methods. The object :class:`django.db.connection
    729 <django.db.backends.DatabaseWrapper>` represents the current database
    730 connection. To use it, call :meth:`connection.cursor()
    731 <django.db.backends.DatabaseWrapper.cursor>` to get a cursor object. Then, call
    732 ``cursor.execute(sql, [params])`` to execute the SQL and
    733 :meth:`cursor.fetchone() <django.db.backends.CursorWrapper.fetchone>` or
    734 :meth:`cursor.fetchall() <django.db.backends.CursorWrapper.fetchall>` to return
    735 the resulting rows. For example::
     728module-level methods. See :ref:`raw SQL <topic-db-sql>`.
    736729
    737     def my_custom_sql(self):
    738         from django.db import connection
    739         cursor = connection.cursor()
    740         cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
    741         row = cursor.fetchone()
    742         return row
    743 
    744 :class:`connection <django.db.backends.DatabaseWrapper>` and :class:`cursor
    745 <django.db.backends.CursorWrapper>` mostly implement the standard Python
    746 DB-API -- see :pep:`249` -- with the addition of Django's :ref:`transaction
    747 handling <topics-db-transactions>`. If you're not familiar with the Python
    748 DB-API, note that the SQL statement in :meth:`cursor.execute()
    749 <django.db.backends.CursorWrapper.execute>` uses placeholders, ``"%s"``, rather
    750 than adding parameters directly within the SQL. If you use this technique, the
    751 underlying database library will automatically add quotes and escaping to your
    752 parameter(s) as necessary. (Also note that Django expects the ``"%s"``
    753 placeholder, *not* the ``"?"`` placeholder, which is used by the SQLite Python
    754 bindings. This is for the sake of consistency and sanity.)
    755 
    756 A final note: If all you want to do is a custom ``WHERE`` clause, you can use
    757 the :meth:`~QuerySet.extra` lookup method, which lets you add custom SQL to a
    758 query.
    759 
    760730.. _model-inheritance:
    761731
    762732Model inheritance
  • docs/topics/db/sql.txt

     
    55
    66Feel free to write custom SQL statements in custom model methods and
    77module-level methods. The object ``django.db.connection`` represents the
    8 current database connection. To use it, call ``connection.cursor()`` to get a
     8current database connection, and ``django.db.transaction`` represents the
     9current database transaction. To use it, call ``connection.cursor()`` to get a
    910cursor object. Then, call ``cursor.execute(sql, [params])`` to execute the SQL
    1011and ``cursor.fetchone()`` or ``cursor.fetchall()`` to return the resulting
    11 rows. Example::
     12rows, followed by ``transaction.commit_unless_managed()`` to commit the
     13change. Example::
    1214
    1315    def my_custom_sql(self):
    14         from django.db import connection
     16        from django.db import connection, transaction
    1517        cursor = connection.cursor()
    1618        cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
    1719        row = cursor.fetchone()
     20        cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
     21        transaction.commit_unless_managed()
    1822        return row
    1923
    2024``connection`` and ``cursor`` mostly implement the standard `Python DB-API`_
     
    3135use the ``where``, ``tables`` and ``params`` arguments to the standard lookup
    3236API.
    3337
     38Transaction handling
     39--------------------
     40
     41Django :ref:`transaction handling <topic-db-transactions>` offers a choice
     42of different behaviors, if you're using a database that supports
     43transactions.
     44
     45Raw SQL users should note that all their commands are actually always run
     46inside a transaction, even when using Django in auto-commit mode. As per the
     47standard `Python DB-API`, all database connections come wrapped inside a
     48transaction. In the default Django auto-commit mode, it simulates
     49auto-commit by regularly committing this underlying transaction, e.g. in
     50``model.save()``.
     51
     52As a result, raw SQL users should call
     53``transaction.commit_unless_managed()`` after ``cursor.execute()``, just as
     54``model.save()`` does internally.
     55
     56Raw SQL users with PostgreSQL should note that once a PostgreSQL raises an
     57exception, all subsequent SQL in the same transaction fails with the error
     58"current transaction is aborted, queries ignored until end of transaction
     59block". As a result, raw SQL users with PostgreSQL should additionally wrap
     60commands that may throw IntegrityError inside savepoints. Example::
     61
     62    try:
     63        sid = transaction.savepoint()
     64        cursor.execute(XXX)
     65        transaction.savepoint_commit(sid)
     66    except IntegrityError:
     67        transaction.savepoint_rollback(sid)
     68        raise
     69
    3470.. _Python DB-API: http://www.python.org/peps/pep-0249.html
    3571
Back to Top