On 2011-02-24 6:40 PM, I wrote:
I am planning on working on the documentation this weekend.

And here's my attempt. The language is a bit poor at some places but I can't think of anything better.

I tried to be more strict about using "subquery" when talking about WITHs in general since INSERT/UPDATE/DELETE is not a subquery in my book.


Regards,
Marko Tiikkaja
*** a/doc/src/sgml/queries.sgml
--- b/doc/src/sgml/queries.sgml
***************
*** 1526,1532 **** SELECT <replaceable>select_list</replaceable> FROM 
<replaceable>table_expression
  
  
   <sect1 id="queries-with">
!   <title><literal>WITH</literal> Queries (Common Table Expressions)</title>
  
    <indexterm zone="queries-with">
     <primary>WITH</primary>
--- 1526,1532 ----
  
  
   <sect1 id="queries-with">
!   <title><literal>WITH</literal> Statements (Common Table Expressions)</title>
  
    <indexterm zone="queries-with">
     <primary>WITH</primary>
***************
*** 1539,1549 **** SELECT <replaceable>select_list</replaceable> FROM 
<replaceable>table_expression
    </indexterm>
  
    <para>
!    <literal>WITH</> provides a way to write subqueries for use in a larger
!    query.  The subqueries, which are often referred to as Common Table
     Expressions or <acronym>CTE</acronym>s, can be thought of as defining
!    temporary tables that exist just for this query.  One use of this feature
!    is to break down complicated queries into simpler parts.  An example is:
  
  <programlisting>
  WITH regional_sales AS (
--- 1539,1559 ----
    </indexterm>
  
    <para>
!    <literal>WITH</> provides a way to write auxiliary statements for use in a
!    larger query.  These statements, which are often referred to as Common 
Table
     Expressions or <acronym>CTE</acronym>s, can be thought of as defining
!    temporary tables that exist just for this query.
!   </para>
! 
!  <sect2 id="subqueries-with">
!    <title>SELECT Queries</title>
! 
!    <indexterm>
!     <primary>*</primary>
!    </indexterm>
!   <para>
!    One use of this feature is to break down complicated queries into simpler
!    parts.  An example is:
  
  <programlisting>
  WITH regional_sales AS (
***************
*** 1806,1811 **** SELECT n FROM t LIMIT 100;
--- 1816,1917 ----
     In each case it effectively provides temporary table(s) that can
     be referred to in the main command.
    </para>
+  </sect2>
+  <sect2 id="modifying-with">
+    <title>Data-Modifying Statements</title>
+ 
+    <indexterm>
+     <primary>*</primary>
+    </indexterm>
+ 
+    <para>
+     You can also use data-modifying statements <command>INSERT</>,
+     <command>UPDATE</> and <command>DELETE</> in <literal>WITH</>.  This 
allows
+     you to perform many different operations in the same query.  An example 
is:
+ 
+ <programlisting>
+ WITH moved_rows AS (
+     DELETE FROM ONLY products
+     WHERE
+         "date" &gt;= '2010-10-01' AND
+         "date" &lt; '2010-11-01'
+     RETURNING *
+ )
+ INSERT INTO products_log
+ SELECT * FROM moved_rows;
+ </programlisting>
+ 
+     which moves rows from "products" to "products_log".  In the example above,
+     the <literal>WITH</> clause is attached to the <command>INSERT</>, not the
+     <command>SELECT</>.  This is important, because data-modifying statements
+     are not allowed in <literal>WITH</> clauses which are not attached to the
+     top level statement.  However, normal <literal>WITH</> visibility rules
+     apply: it is possible to refer to a data-modifying <literal>WITH</> from a
+     subquery.
+    </para>
+ 
+    <para>
+     Recursive self-references in data-modifying statements are not
+     allowed.  In some cases it is possible to work around this limitation by
+     referring to the output of a recursive <literal>WITH</>:
+ 
+ <programlisting>
+ WITH RECURSIVE included_parts(sub_part, part) AS (
+     SELECT sub_part, part FROM parts WHERE part = 'our_product'
+   UNION ALL
+     SELECT p.sub_part, p.part
+     FROM included_parts pr, parts p
+     WHERE p.part = pr.sub_part
+   )
+ DELETE FROM parts
+   WHERE part IN (SELECT part FROM included_parts);
+ </programlisting>
+ 
+     The above query would remove all direct and indirect subparts of a 
product.
+    </para>
+ 
+    <para>
+     The execution of data-modifying statements in <literal>WITH</> is
+     interleaved with the main plan, and the order in which the statements
+     are executed is arbitrary.  The changes made by data-modifying statements
+     are not visible to the query.
+    </para>
+    <important>
+     <para>
+      Trying to update the same row twice in a single command is not supported.
+      Only one of the modifications takes place, but it is not easy (and
+      sometimes not possible) to reliably predict which one.  This also applies
+      to deleting a row that was already updated in the same command; only the
+      update is performed.  You should generally avoid trying to modify a 
single
+      row twice in a single command.
+     </para>
+    </important>
+ 
+    <para>
+     Data-modifying statements are executed exactly once, and always to
+     completion.  If a <literal>WITH</> containing a data-modifying statement
+     is not referred to in the query, it is possible to omit the
+     <literal>RETURNING</> clause:
+ 
+ <programlisting>
+ WITH t AS (
+     DELETE FROM foo
+ )
+ DELETE FROM bar;
+ </programlisting>
+ 
+     The example above would remove all rows from tables "foo" and "bar".  The
+     number of affected rows returned to the client would only include rows
+     removed from "bar". 
+    </para>
+ 
+    <para>
+     Any table used as the target of a data-modifying statement in
+     <literal>WITH</> must not contain a conditional rule, an <literal>ALSO</>
+     rule or an <literal>INSTEAD</> rule with multiple statements.
+    </para>
+ 
+  </sect2>
  
   </sect1>
  
*** a/doc/src/sgml/ref/delete.sgml
--- b/doc/src/sgml/ref/delete.sgml
***************
*** 89,95 **** DELETE FROM [ ONLY ] <replaceable 
class="PARAMETER">table</replaceable> [ [ AS ]
      <listitem>
       <para>
        The <literal>WITH</literal> clause allows you to specify one or more
!       subqueries that can be referenced by name in the <command>DELETE</>
        query. See <xref linkend="queries-with"> and <xref linkend="sql-select">
        for details.
       </para>
--- 89,95 ----
      <listitem>
       <para>
        The <literal>WITH</literal> clause allows you to specify one or more
!       statements whose results can be referenced by name in the 
<command>DELETE</>
        query. See <xref linkend="queries-with"> and <xref linkend="sql-select">
        for details.
       </para>
*** a/doc/src/sgml/ref/insert.sgml
--- b/doc/src/sgml/ref/insert.sgml
***************
*** 90,96 **** INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ 
( <replaceable
      <listitem>
       <para>
        The <literal>WITH</literal> clause allows you to specify one or more
!       subqueries that can be referenced by name in the <command>INSERT</>
        query. See <xref linkend="queries-with"> and <xref linkend="sql-select">
        for details.
       </para>
--- 90,96 ----
      <listitem>
       <para>
        The <literal>WITH</literal> clause allows you to specify one or more
!       statements whose results can be referenced by name in the 
<command>INSERT</>
        query. See <xref linkend="queries-with"> and <xref linkend="sql-select">
        for details.
       </para>
*** a/doc/src/sgml/ref/select.sgml
--- b/doc/src/sgml/ref/select.sgml
***************
*** 58,64 **** SELECT [ ALL | DISTINCT [ ON ( <replaceable 
class="parameter">expression</replac
  
  <phrase>and <replaceable class="parameter">with_query</replaceable> 
is:</phrase>
  
!     <replaceable class="parameter">with_query_name</replaceable> [ ( 
<replaceable class="parameter">column_name</replaceable> [, ...] ) ] AS ( 
<replaceable class="parameter">select</replaceable> )
  
  TABLE { [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * 
] | <replaceable class="parameter">with_query_name</replaceable> }
  </synopsis>
--- 58,64 ----
  
  <phrase>and <replaceable class="parameter">with_query</replaceable> 
is:</phrase>
  
!     <replaceable class="parameter">with_query_name</replaceable> [ ( 
<replaceable class="parameter">column_name</replaceable> [, ...] ) ] AS ( 
<replaceable class="parameter">select</replaceable> | <replaceable 
class="parameter">insert</replaceable> | <replaceable 
class="parameter">update</replaceable> | <replaceable 
class="parameter">delete</replaceable> )
  
  TABLE { [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * 
] | <replaceable class="parameter">with_query_name</replaceable> }
  </synopsis>
***************
*** 206,233 **** TABLE { [ ONLY ] <replaceable 
class="parameter">table_name</replaceable> [ * ] |
  
     <para>
      The <literal>WITH</literal> clause allows you to specify one or more
!     subqueries that can be referenced by name in the primary query.
!     The subqueries effectively act as temporary tables or views
!     for the duration of the primary query.
     </para>
  
     <para>
      A name (without schema qualification) must be specified for each
!     <literal>WITH</literal> query.  Optionally, a list of column names
      can be specified; if this is omitted,
!     the column names are inferred from the subquery.
     </para>
  
     <para>
      If <literal>RECURSIVE</literal> is specified, it allows a
!     subquery to reference itself by name.  Such a subquery must have
!     the form
  <synopsis>
  <replaceable class="parameter">non_recursive_term</replaceable> UNION [ ALL | 
DISTINCT ] <replaceable class="parameter">recursive_term</replaceable>
  </synopsis>
      where the recursive self-reference must appear on the right-hand
      side of the <literal>UNION</>.  Only one recursive self-reference
!     is permitted per query.
     </para>
  
     <para>
--- 206,241 ----
  
     <para>
      The <literal>WITH</literal> clause allows you to specify one or more
!     read-only (<literal>SELECT</literal>) or data-modifying statements whose
!     results can be referenced by name in the primary query.  These statements
!     effectively act as temporary tables or views for the duration of the
!     primary query. Currently only <literal>SELECT</literal>,
!     <literal>INSERT</literal>, <literal>UPDATE</literal> and
!     <literal>DELETE</literal> statements are supported in
!     <literal>WITH</literal>.
     </para>
  
     <para>
      A name (without schema qualification) must be specified for each
!     <literal>WITH</literal> statement.  Optionally, a list of column names
      can be specified; if this is omitted,
!     the column names are inferred from the statement.
     </para>
  
     <para>
      If <literal>RECURSIVE</literal> is specified, it allows a
!     <literal>SELECT</literal> subquery to reference itself by name.  Such a
!     subquery must have the form
  <synopsis>
  <replaceable class="parameter">non_recursive_term</replaceable> UNION [ ALL | 
DISTINCT ] <replaceable class="parameter">recursive_term</replaceable>
  </synopsis>
      where the recursive self-reference must appear on the right-hand
      side of the <literal>UNION</>.  Only one recursive self-reference
!     is permitted per query.  Recursive data-modifying statements are not
!     supported, but you can use the results of a recursive
!     <literal>SELECT</literal> query in
!     a data-modifying statement.  See <xref linkend="queries-with"> for
!     an example.
     </para>
  
     <para>
***************
*** 241,247 **** TABLE { [ ONLY ] <replaceable 
class="parameter">table_name</replaceable> [ * ] |
     </para>
  
     <para>
!     A useful property of <literal>WITH</literal> queries is that they
      are evaluated only once per execution of the primary query,
      even if the primary query refers to them more than once.
     </para>
--- 249,255 ----
     </para>
  
     <para>
!     A useful property of <literal>WITH</literal> statements is that they
      are evaluated only once per execution of the primary query,
      even if the primary query refers to them more than once.
     </para>
*** a/doc/src/sgml/ref/update.sgml
--- b/doc/src/sgml/ref/update.sgml
***************
*** 85,91 **** UPDATE [ ONLY ] <replaceable 
class="PARAMETER">table</replaceable> [ [ AS ] <rep
      <listitem>
       <para>
        The <literal>WITH</literal> clause allows you to specify one or more
!       subqueries that can be referenced by name in the <command>UPDATE</>
        query. See <xref linkend="queries-with"> and <xref linkend="sql-select">
        for details.
       </para>
--- 85,91 ----
      <listitem>
       <para>
        The <literal>WITH</literal> clause allows you to specify one or more
!       statements whose results can be referenced by name in the 
<command>UPDATE</>
        query. See <xref linkend="queries-with"> and <xref linkend="sql-select">
        for details.
       </para>
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to