(or RETURNING), but only when the output name is not any SQL keyword.
This seems as close as we can get to the standard's syntax without a
great deal of thrashing. Original patch by Hiroshi Saito, amended by me.
-<!-- $PostgreSQL: pgsql/doc/src/sgml/queries.sgml,v 1.44 2007/02/01 19:10:24 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/queries.sgml,v 1.45 2008/02/15 22:17:06 tgl Exp $ -->
<chapter id="queries">
<title>Queries</title>
<synopsis>
FROM <replaceable>table_reference</replaceable> <replaceable>alias</replaceable>
</synopsis>
- The <literal>AS</literal> key word is noise.
+ The <literal>AS</literal> key word is optional noise.
<replaceable>alias</replaceable> can be any identifier.
</para>
</para>
<para>
- If no output column name is specified using <literal>AS</>, the system assigns a
- default name. For simple column references, this is the name of the
- referenced column. For function
+ If no output column name is specified using <literal>AS</>,
+ the system assigns a default column name. For simple column references,
+ this is the name of the referenced column. For function
calls, this is the name of the function. For complex expressions,
the system will generate a generic name.
</para>
+ <para>
+ The <literal>AS</> keyword is optional, but only if the new column
+ name does not match any
+ <productname>PostgreSQL</productname> keyword (see <xref
+ linkend="sql-keywords-appendix">). To avoid an accidental match to
+ a keyword, you can double-quote the column name. For example,
+ <literal>VALUE</> is a keyword, so this does not work:
+<programlisting>
+SELECT a value, b + c AS sum FROM ...
+</programlisting>
+ but this does:
+<programlisting>
+SELECT a "value", b + c AS sum FROM ...
+</programlisting>
+ For protection against possible
+ future keyword additions, it is recommended that you always either
+ write <literal>AS</literal> or double-quote the output column name.
+ </para>
+
<note>
<para>
The naming of output columns here is different from that done in
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/delete.sgml,v 1.32 2007/11/28 15:42:31 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/delete.sgml,v 1.33 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation
-->
DELETE FROM [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> ]
[ USING <replaceable class="PARAMETER">usinglist</replaceable> ]
[ WHERE <replaceable class="PARAMETER">condition</replaceable> | WHERE CURRENT OF <replaceable class="PARAMETER">cursor_name</replaceable> ]
- [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
+ [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
</synopsis>
</refsynopsisdiv>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/insert.sgml,v 1.35 2007/01/31 23:26:04 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/insert.sgml,v 1.36 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation
-->
<synopsis>
INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) ]
{ DEFAULT VALUES | VALUES ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ...] | <replaceable class="PARAMETER">query</replaceable> }
- [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
+ [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
</synopsis>
</refsynopsisdiv>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.102 2007/11/28 15:42:31 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.103 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation
-->
<refsynopsisdiv>
<synopsis>
SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replaceable> [, ...] ) ] ]
- * | <replaceable class="parameter">expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...]
+ * | <replaceable class="parameter">expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...]
[ FROM <replaceable class="parameter">from_item</replaceable> [, ...] ]
[ WHERE <replaceable class="parameter">condition</replaceable> ]
[ GROUP BY <replaceable class="parameter">expression</replaceable> [, ...] ]
<literal>SELECT</> and <literal>FROM</>) specifies expressions
that form the output rows of the <command>SELECT</command>
statement. The expressions can (and usually do) refer to columns
- computed in the <literal>FROM</> clause. Using the clause
- <literal>AS <replaceable
- class="parameter">output_name</replaceable></literal>, another
- name can be specified for an output column. This name is
- primarily used to label the column for display. It can also be
- used to refer to the column's value in <literal>ORDER BY</> and
- <literal>GROUP BY</> clauses, but not in the <literal>WHERE</> or
- <literal>HAVING</> clauses; there you must write out the
- expression instead.
+ computed in the <literal>FROM</> clause.
+ </para>
+
+ <para>
+ Just as in a table, every output column of a <command>SELECT</command>
+ has a name. In a simple <command>SELECT</command> this name is just
+ used to label the column for display, but when the <command>SELECT</>
+ is a sub-query of a larger query, the name is seen by the larger query
+ as the column name of the virtual table produced by the sub-query.
+ To specify the name to use for an output column, write
+ <literal>AS</> <replaceable class="parameter">output_name</replaceable>
+ after the column's expression. (You can omit <literal>AS</literal>,
+ but only if the desired output name does not match any
+ <productname>PostgreSQL</productname> keyword (see <xref
+ linkend="sql-keywords-appendix">). For protection against possible
+ future keyword additions, it is recommended that you always either
+ write <literal>AS</literal> or double-quote the output name.)
+ If you do not specify a column name, a name is chosen automatically
+ by <productname>PostgreSQL</productname>. If the column's expression
+ is a simple column reference then the chosen name is the same as that
+ column's name; in more complex cases a generated name looking like
+ <literal>?column<replaceable>N</>?</literal> is usually chosen.
+ </para>
+
+ <para>
+ An output column's name can be used to refer to the column's value in
+ <literal>ORDER BY</> and <literal>GROUP BY</> clauses, but not in the
+ <literal>WHERE</> or <literal>HAVING</> clauses; there you must write
+ out the expression instead.
</para>
<para>
Instead of an expression, <literal>*</literal> can be written in
the output list as a shorthand for all the columns of the selected
- rows. Also, one can write <literal><replaceable
+ rows. Also, you can write <literal><replaceable
class="parameter">table_name</replaceable>.*</literal> as a
- shorthand for the columns coming from just that table.
+ shorthand for the columns coming from just that table. In these
+ cases it is not possible to specify new names with <literal>AS</>;
+ the output column names will be the same as the table columns' names.
</para>
</refsect2>
<para>
The ordinal number refers to the ordinal (left-to-right) position
- of the result column. This feature makes it possible to define an
+ of the output column. This feature makes it possible to define an
ordering on the basis of a column that does not have a unique
name. This is never absolutely necessary because it is always
- possible to assign a name to a result column using the
+ possible to assign a name to an output column using the
<literal>AS</> clause.
</para>
<para>
It is also possible to use arbitrary expressions in the
<literal>ORDER BY</literal> clause, including columns that do not
- appear in the <command>SELECT</command> result list. Thus the
+ appear in the <command>SELECT</command> output list. Thus the
following statement is valid:
<programlisting>
SELECT name FROM distributors ORDER BY code;
<para>
If an <literal>ORDER BY</> expression is a simple name that
- matches both a result column name and an input column name,
- <literal>ORDER BY</> will interpret it as the result column name.
+ matches both an output column name and an input column name,
+ <literal>ORDER BY</> will interpret it as the output column name.
This is the opposite of the choice that <literal>GROUP BY</> will
make in the same situation. This inconsistency is made to be
compatible with the SQL standard.
</refsect2>
<refsect2>
- <title>The <literal>AS</literal> Key Word</title>
+ <title>Omitting the <literal>AS</literal> Key Word</title>
+
+ <para>
+ In the SQL standard, the optional key word <literal>AS</> can be
+ omitted before an output column name whenever the new column name
+ is a valid column name (that is, not the same as any reserved
+ keyword). <productname>PostgreSQL</productname> is slightly more
+ restrictive: <literal>AS</> is required if the new column name
+ matches any keyword at all, reserved or not. Recommended practice is
+ to use <literal>AS</> or double-quote output column names, to prevent
+ any possible conflict against future keyword additions.
+ </para>
<para>
- In the SQL standard, the optional key word <literal>AS</> is just
- noise and can be omitted without affecting the meaning. The
- <productname>PostgreSQL</productname> parser requires this key
- word when renaming output columns because the type extensibility
- features lead to parsing ambiguities without it.
- <literal>AS</literal> is optional in <literal>FROM</literal>
- items, however.
+ In <literal>FROM</literal> items, both the standard and
+ <productname>PostgreSQL</productname> allow <literal>AS</> to
+ be omitted before an alias that is an unreserved keyword. But
+ this is impractical for output column names, because of syntactic
+ ambiguities.
</para>
</refsect2>
<para>
In the SQL-92 standard, an <literal>ORDER BY</literal> clause can
- only use result column names or numbers, while a <literal>GROUP
+ only use output column names or numbers, while a <literal>GROUP
BY</literal> clause can only use expressions based on input column
names. <productname>PostgreSQL</productname> extends each of
these clauses to allow the other choice as well (but it uses the
<productname>PostgreSQL</productname> also allows both clauses to
specify arbitrary expressions. Note that names appearing in an
expression will always be taken as input-column names, not as
- result-column names.
+ output-column names.
</para>
<para>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/select_into.sgml,v 1.39 2007/01/09 02:14:10 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/select_into.sgml,v 1.40 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation
-->
<refsynopsisdiv>
<synopsis>
SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replaceable> [, ...] ) ] ]
- * | <replaceable class="PARAMETER">expression</replaceable> [ AS <replaceable class="PARAMETER">output_name</replaceable> ] [, ...]
+ * | <replaceable class="PARAMETER">expression</replaceable> [ [ AS ] <replaceable class="PARAMETER">output_name</replaceable> ] [, ...]
INTO [ TEMPORARY | TEMP ] [ TABLE ] <replaceable class="PARAMETER">new_table</replaceable>
[ FROM <replaceable class="PARAMETER">from_item</replaceable> [, ...] ]
[ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.45 2007/11/28 15:42:31 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.46 2008/02/15 22:17:06 tgl Exp $
PostgreSQL documentation
-->
( <replaceable class="PARAMETER">column</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) } [, ...]
[ FROM <replaceable class="PARAMETER">fromlist</replaceable> ]
[ WHERE <replaceable class="PARAMETER">condition</replaceable> | WHERE CURRENT OF <replaceable class="PARAMETER">cursor_name</replaceable> ]
- [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
+ [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ [ AS ] <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
</synopsis>
</refsynopsisdiv>
-<!-- $PostgreSQL: pgsql/doc/src/sgml/sql.sgml,v 1.46 2007/02/16 03:50:29 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/sql.sgml,v 1.47 2008/02/15 22:17:06 tgl Exp $ -->
<chapter id="sql-intro">
<title>SQL</title>
<synopsis>
SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replaceable> [, ...] ) ] ]
- * | <replaceable class="PARAMETER">expression</replaceable> [ AS <replaceable class="PARAMETER">output_name</replaceable> ] [, ...]
+ * | <replaceable class="PARAMETER">expression</replaceable> [ [ AS ] <replaceable class="PARAMETER">output_name</replaceable> ] [, ...]
[ INTO [ TEMPORARY | TEMP ] [ TABLE ] <replaceable class="PARAMETER">new_table</replaceable> ]
[ FROM <replaceable class="PARAMETER">from_item</replaceable> [, ...] ]
[ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.606 2008/02/07 21:07:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.607 2008/02/15 22:17:06 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
%nonassoc BETWEEN
%nonassoc IN_P
%left POSTFIXOP /* dummy for postfix Op rules */
+%nonassoc IDENT /* to support target_el without AS */
%left Op OPERATOR /* multi-character ops and user-defined operators */
%nonassoc NOTNULL
%nonassoc ISNULL
| target_list ',' target_el { $$ = lappend($1, $3); }
;
-/* AS is not optional because shift/red conflict with unary ops */
target_el: a_expr AS ColLabel
{
$$ = makeNode(ResTarget);
$$->val = (Node *)$1;
$$->location = @1;
}
+ /*
+ * We support omitting AS only for column labels that aren't
+ * any known keyword. There is an ambiguity against postfix
+ * operators: is "a ! b" an infix expression, or a postfix
+ * expression and a column label? We prefer to resolve this
+ * as an infix expression, which we accomplish by assigning
+ * IDENT a precedence higher than POSTFIXOP.
+ */
+ | a_expr IDENT
+ {
+ $$ = makeNode(ResTarget);
+ $$->name = $2;
+ $$->indirection = NIL;
+ $$->val = (Node *)$1;
+ $$->location = @1;
+ }
| a_expr
{
$$ = makeNode(ResTarget);
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.360 2008/02/14 14:54:48 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.361 2008/02/15 22:17:06 tgl Exp $ */
/* Copyright comment */
%{
%nonassoc OVERLAPS
%nonassoc BETWEEN
%nonassoc IN_P
-%left POSTFIXOP /* dummy for postfix Op rules */
-%left Op OPERATOR /* multi-character ops and user-defined operators */
+%left POSTFIXOP /* dummy for postfix Op rules */
+%nonassoc IDENT /* to support target_el without AS */
+%left Op OPERATOR /* multi-character ops and user-defined operators */
%nonassoc NOTNULL
%nonassoc ISNULL
%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN
{ $$ = $1; }
;
-/* AS is not optional because shift/red conflict with unary ops */
target_el: a_expr AS ColLabel
{ $$ = cat_str(3, $1, make_str("as"), $3); }
+ | a_expr IDENT
+ { $$ = cat_str(3, $1, make_str("as"), $2); }
| a_expr
{ $$ = $1; }
| '*'
end loop;
return 5;
end;$$ language plpgsql;
-ERROR: syntax error at or near "fought"
+ERROR: syntax error at or near "the"
LINE 1: select I fought the law, the law won
- ^
+ ^
QUERY: select I fought the law, the law won
CONTEXT: SQL statement in PL/PgSQL function "bad_sql2" near line 3
-- a RETURN expression is mandatory, except for void-returning