]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
reword INSERT explanation
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 19 Jan 2023 14:43:19 +0000 (09:43 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 19 Jan 2023 14:43:19 +0000 (09:43 -0500)
Change-Id: I08460f0a77131c8c1406c3496e9d64a5a26bf6ff

doc/build/tutorial/data_insert.rst

index 4e85f903cf6b074dda909e988d66e8609a9b8cec..2415f21f356fe3b3f1bb21f2f9044ebaebe9f164 100644 (file)
@@ -23,14 +23,17 @@ INSERT statement in SQL, that adds new data into a table.
 
     **ORM Readers** -
 
-    The ORM's means of generating INSERT statements is described in
-    one of two ways; the most common is by using
-    the :term:`unit of work` process which automates the generation of
-    INSERT statements from object state, and is introduced
-    at :ref:`tutorial_inserting_orm`.  The other is by using
-    the :class:`_sql.Insert` construct directly
-    in a manner very similar to that described in this section; this use
-    is introduced at :ref:`tutorial_orm_bulk`.
+    This section details the Core means of generating an individual SQL INSERT
+    statement in order to add new rows to a table. When using the ORM, we
+    normally use another tool that rides on top of this called the
+    :term:`unit of work`, which will automate the production of many INSERT
+    statements at once. However, understanding how the Core handles data
+    creation and manipulation is very useful even when the ORM is running
+    it for us.  Additionally, the ORM supports direct use of INSERT
+    using a feature called :ref:`tutorial_orm_bulk`.
+
+    To skip directly to how to INSERT rows with the ORM using normal
+    unit of work patterns, see :ref:`tutorial_inserting_orm`.
 
 
 The insert() SQL Expression Construct
@@ -64,6 +67,7 @@ available from the :class:`_engine.Compiled` construct as well::
     >>> compiled.params
     {'name': 'spongebob', 'fullname': 'Spongebob Squarepants'}
 
+
 Executing the Statement
 ^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -112,13 +116,23 @@ INSERT usually generates the "values" clause automatically
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 The example above made use of the :meth:`_sql.Insert.values` method to
-explicitly create the VALUES clause of the SQL INSERT statement.   This method
-in fact has some variants that allow for special forms such as multiple rows in
-one statement and insertion of SQL expressions.   However the usual way that
-:class:`_sql.Insert` is used is such that the VALUES clause is generated
-automatically from the parameters passed to the
-:meth:`_engine.Connection.execute` method; below we INSERT two more rows to
-illustrate this:
+explicitly create the VALUES clause of the SQL INSERT statement.   If
+we don't actually use :meth:`_sql.Insert.values` and just print out an "empty"
+statement, we get an INSERT for every column in the table::
+
+    >>> print(insert(user_table))
+    {printsql}INSERT INTO user_account (id, name, fullname) VALUES (:id, :name, :fullname)
+
+If we take an :class:`_sql.Insert` construct that has not had
+:meth:`_sql.Insert.values` called upon it and execute it
+rather than print it, the statement will be compiled to a string based
+on the parameters that we passed to the :meth:`_engine.Connection.execute`
+method, and only include columns relevant to the parameters that were
+passed.   This is actually the usual way that
+:class:`_sql.Insert` is used to insert rows without having to type out
+an explicit VALUES clause.   The example below illustrates a two-column
+INSERT statement being executed with a list of parameters at once:
+
 
 .. sourcecode:: pycon+sql
 
@@ -198,23 +212,17 @@ construct automatically.
         ('sandy', 'sandy@squirrelpower.org')]
         COMMIT{stop}
 
-.. _tutorial_insert_from_select:
+    With that, we have some more interesting data in our tables that we will
+    make use of in the upcoming sections.
 
-INSERT...FROM SELECT
-^^^^^^^^^^^^^^^^^^^^^
+.. tip:: A true "empty" INSERT that inserts only the "defaults" for a table
+   without including any explicit values at all is generated if we indicate
+   :meth:`_sql.Insert.values` with no arguments; not every database backend
+   supports this, but here's what SQLite produces::
 
-The :class:`_sql.Insert` construct can compose
-an INSERT that gets rows directly from a SELECT using the :meth:`_sql.Insert.from_select`
-method::
+    >>> print(insert(user_table).values().compile(engine))
+    {printsql}INSERT INTO user_account DEFAULT VALUES
 
-    >>> 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)
-    {printsql}INSERT INTO address (user_id, email_address)
-    SELECT user_account.id, user_account.name || :name_1 AS anon_1
-    FROM user_account
 
 .. _tutorial_insert_returning:
 
@@ -263,6 +271,34 @@ as in the example below that builds upon the example stated in
     :ref:`engine_insertmanyvalues` for background on this feature.
 
 
+.. _tutorial_insert_from_select:
+
+INSERT...FROM SELECT
+^^^^^^^^^^^^^^^^^^^^^
+
+A less used feature of :class:`_sql.Insert`, but here for completeness, the
+:class:`_sql.Insert` construct can compose an INSERT that gets rows directly
+from a SELECT using the :meth:`_sql.Insert.from_select` method.
+This method accepts a :func:`_sql.select` construct, which is discussed in the
+next section, along with a list of column names to be targeted in the
+actual INSERT.  In the example below, rows are added to the ``address``
+table which are derived from rows in the ``user_account`` table, giving each
+user a free email address at ``aol.com``::
+
+    >>> 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)
+    {printsql}INSERT INTO address (user_id, email_address)
+    SELECT user_account.id, user_account.name || :name_1 AS anon_1
+    FROM user_account
+
+This construct is used when one wants to copy data from
+some other part of the database directly into a new set of rows, without
+actually fetching and re-sending the data from the client.
+
+
 .. seealso::
 
     :class:`_sql.Insert` - in the SQL Expression API documentation