('sandy', 'sandy@squirrelpower.org'))
COMMIT{stop}
-Other INSERT Options
-^^^^^^^^^^^^^^^^^^^^^
+.. _tutorial_insert_from_select:
-A quick overview of some other patterns that are available with :func:`_sql.insert`:
+INSERT...FROM SELECT
+^^^^^^^^^^^^^^^^^^^^^
-* **INSERT..FROM SELECT** - the :class:`_sql.Insert` construct can compose
- an INSERT that gets rows directly from a SELECT using the :meth:`_sql.Insert.from_select`
- method::
+The :class:`_sql.Insert` construct can compose
+an INSERT that gets rows directly from a SELECT using the :meth:`_sql.Insert.from_select`
+method::
>>> select_stmt = select(user_table.c.id, user_table.c.name + "@aol.com")
>>> insert_stmt = insert(address_table).from_select(
SELECT user_account.id, user_account.name || :name_1 AS anon_1
FROM user_account
- ..
+.. _tutorial_insert_returning:
+
+INSERT...RETURNING
+^^^^^^^^^^^^^^^^^^^^^
+
+The RETURNING clause for supported backends is used
+automatically in order to retrieve the last inserted primary key value
+as well as the values for server defaults. However the RETURNING clause
+may also be specified explicitly using the :meth:`_sql.Insert.returning`
+method; in this case, the :class:`_engine.Result`
+object that's returned when the statement is executed has rows which
+can be fetched. It is only supported for single-statement
+forms, and for some backends may only support single-row INSERT statements
+overall::
+
+ >>> insert_stmt = insert(address_table).returning(address_table.c.id, address_table.c.email_address)
+ >>> print(insert_stmt)
+ {opensql}INSERT INTO address (id, user_id, email_address)
+ VALUES (:id, :user_id, :email_address)
+ RETURNING address.id, address.email_address
+
-* **RETURNING clause** - the RETURNING clause for supported backends is used
- automatically in order to retrieve the last inserted primary key value
- as well as the values for server defaults. However the RETURNING clause
- may also be specified explicitly using the :meth:`_sql.Insert.returning`
- method; in this case, the :class:`_engine.Result`
- object that's returned when the statement is executed has rows which
- can be fetched. It is only supported for single-statement
- forms, and for some backends may only support single-row INSERT statements
- overall. It can also be combined with :meth:`_sql.Insert.from_select`,
- as in the example below that builds upon the previous example::
+It can also be combined with :meth:`_sql.Insert.from_select`,
+as in the example below that builds upon the example stated in
+:ref:`tutorial_insert_from_select`::
+ >>> select_stmt = select(user_table.c.id, user_table.c.name + "@aol.com")
+ >>> insert_stmt = insert(address_table).from_select(
+ ... ["user_id", "email_address"], select_stmt
+ ... )
>>> print(insert_stmt.returning(address_table.c.id, address_table.c.email_address))
{opensql}INSERT INTO address (user_id, email_address)
SELECT user_account.id, user_account.name || :name_1 AS anon_1
FROM user_account RETURNING address.id, address.email_address
- ..
-
.. seealso::
:class:`_sql.Insert` - in the SQL Expression API documentation
named_with_column = False
_return_defaults = None
+ _returning = ()
is_dml = True
def returning(self, *cols):
r"""Add a :term:`RETURNING` or equivalent clause to this statement.
- e.g.::
+ e.g.:
+
+ .. sourcecode:: pycon+sql
- stmt = table.update().\
- where(table.c.data == 'value').\
- values(status='X').\
- returning(table.c.server_flag,
- table.c.updated_timestamp)
+ >>> stmt = (
+ ... table.update()
+ ... .where(table.c.data == "value")
+ ... .values(status="X")
+ ... .returning(table.c.server_flag, table.c.updated_timestamp)
+ ... )
+ >>> print(stmt)
+ UPDATE some_table SET status=:status
+ WHERE some_table.data = :data_1
+ RETURNING some_table.server_flag, some_table.updated_timestamp
- for server_flag, updated_timestamp in connection.execute(stmt):
- print(server_flag, updated_timestamp)
+ The method may be invoked multiple times to add new entries to the
+ list of expressions to be returned.
+
+ .. versionadded:: 1.4.0b2 The method may be invoked multiple times to
+ add new entries to the list of expressions to be returned.
The given collection of column expressions should be derived from the
table that is the target of the INSERT, UPDATE, or DELETE. While
:class:`_schema.Column` objects are typical, the elements can also be
- expressions::
+ expressions:
+
+ .. sourcecode:: pycon+sql
- stmt = table.insert().returning(
- (table.c.first_name + " " + table.c.last_name).
- label('fullname'))
+ >>> stmt = table.insert().returning(
+ ... (table.c.first_name + " " + table.c.last_name).label("fullname")
+ ... )
+ >>> print(stmt)
+ INSERT INTO some_table (first_name, last_name)
+ VALUES (:first_name, :last_name)
+ RETURNING some_table.first_name || :first_name_1 || some_table.last_name AS fullname
Upon compilation, a RETURNING clause, or database equivalent,
will be rendered within the statement. For INSERT and UPDATE,
towards efficient fetching of server-side defaults and triggers
for single-row INSERTs or UPDATEs.
+ :ref:`tutorial_insert_returning` - in the :ref:`unified_tutorial`
- """
+ """ # noqa E501
if self._return_defaults:
raise exc.InvalidRequestError(
"return_defaults() is already configured on this statement"
)
- if self._returning:
- util.warn(
- "The returning() method does not currently support multiple "
- "additive calls. The existing RETURNING clause being "
- "replaced by new columns."
- )
- self._returning = cols
+ self._returning += cols
def _exported_columns_iterator(self):
"""Return the RETURNING columns as a sequence for this statement.
"""
- return self._returning or ()
+ return self._returning
@property
def exported_columns(self):
.. seealso::
- :ref:`coretutorial_insert_expressions` - in the 1.x tutorial
+ :ref:`coretutorial_insert_expressions` - in the
+ :ref:`1.x tutorial <sqlexpression_toplevel>`
- :ref:`tutorial_core_insert` - in the 2.0 tutorial
+ :ref:`tutorial_core_insert` - in the :ref:`unified_tutorial`
:param table: :class:`_expression.TableClause`
.. seealso::
- :ref:`inserts_and_updates` - in the 1.x tutorial
+ :ref:`inserts_and_updates` - in the
+ :ref:`1.x tutorial <sqlexpression_toplevel>`
- :ref:`tutorial_core_update_delete` - in the 2.0 tutorial
+ :ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
self._preserve_parameter_order = preserve_parameter_order
super(Update, self).__init__(table, values, prefixes)
self._bind = bind
- self._returning = returning
+ if returning:
+ self._returning = returning
if whereclause is not None:
self._where_criteria += (
coercions.expect(roles.WhereHavingRole, whereclause),
.. seealso::
- :ref:`inserts_and_updates` - in the 1.x tutorial
+ :ref:`inserts_and_updates` - in the
+ :ref:`1.x tutorial <sqlexpression_toplevel>`
- :ref:`tutorial_core_update_delete` - in the 2.0 tutorial
+ :ref:`tutorial_core_update_delete` - in the :ref:`unified_tutorial`
:param table: The table to delete rows from.
self.table = coercions.expect(
roles.DMLTableRole, table, apply_propagate_attrs=self
)
- self._returning = returning
+ if returning:
+ self._returning = returning
if prefixes:
self._setup_prefixes(prefixes)