mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Add UPDATE tab SET ROW (col, ...) = (val, ...) for updating
multiple columns Susanne Ebrecht
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
			
		||||
<!--
 | 
			
		||||
$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.38 2006/08/12 02:52:03 tgl Exp $
 | 
			
		||||
$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.39 2006/09/02 20:34:47 momjian Exp $
 | 
			
		||||
PostgreSQL documentation
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +21,8 @@ PostgreSQL documentation
 | 
			
		||||
 <refsynopsisdiv>
 | 
			
		||||
<synopsis>
 | 
			
		||||
UPDATE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> ]
 | 
			
		||||
    SET <replaceable class="PARAMETER">column</replaceable> = { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...]
 | 
			
		||||
    [ SET <replaceable class="PARAMETER">column</replaceable> = { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] |
 | 
			
		||||
      SET ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) = ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ...] ]
 | 
			
		||||
    [ FROM <replaceable class="PARAMETER">fromlist</replaceable> ]
 | 
			
		||||
    [ WHERE <replaceable class="PARAMETER">condition</replaceable> ]
 | 
			
		||||
    [ RETURNING * | <replaceable class="parameter">output_expression</replaceable> [ AS <replaceable class="parameter">output_name</replaceable> ] [, ...] ]
 | 
			
		||||
@@ -250,6 +251,10 @@ UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama';
 | 
			
		||||
<programlisting>
 | 
			
		||||
UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
 | 
			
		||||
  WHERE city = 'San Francisco' AND date = '2003-07-03';
 | 
			
		||||
</programlisting>
 | 
			
		||||
<programlisting>
 | 
			
		||||
UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT)
 | 
			
		||||
  WHERE city = 'San Francisco' AND date = '2003-07-03';
 | 
			
		||||
</programlisting>
 | 
			
		||||
  </para>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * IDENTIFICATION
 | 
			
		||||
 *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.560 2006/09/02 18:17:17 momjian Exp $
 | 
			
		||||
 *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.561 2006/09/02 20:34:47 momjian Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * HISTORY
 | 
			
		||||
 *	  AUTHOR			DATE			MAJOR EVENT
 | 
			
		||||
@@ -237,7 +237,8 @@ static void doNegateFloat(Value *v);
 | 
			
		||||
				name_list from_clause from_list opt_array_bounds
 | 
			
		||||
				qualified_name_list any_name any_name_list
 | 
			
		||||
				any_operator expr_list attrs
 | 
			
		||||
				target_list update_target_list insert_column_list
 | 
			
		||||
				target_list update_col_list update_target_list
 | 
			
		||||
				update_value_list insert_column_list
 | 
			
		||||
				values_list def_list indirection opt_indirection
 | 
			
		||||
				group_clause TriggerFuncArgs select_limit
 | 
			
		||||
				opt_select_limit opclass_item_list
 | 
			
		||||
@@ -308,7 +309,8 @@ static void doNegateFloat(Value *v);
 | 
			
		||||
%type <jexpr>	joined_table
 | 
			
		||||
%type <range>	relation_expr
 | 
			
		||||
%type <range>	relation_expr_opt_alias
 | 
			
		||||
%type <target>	target_el update_target_el insert_column_item
 | 
			
		||||
%type <target>	target_el update_target_el update_col_list_el insert_column_item
 | 
			
		||||
%type <list>	update_target_lists_list update_target_lists_el
 | 
			
		||||
 | 
			
		||||
%type <typnam>	Typename SimpleTypename ConstTypename
 | 
			
		||||
				GenericType Numeric opt_float
 | 
			
		||||
@@ -5537,6 +5539,20 @@ UpdateStmt: UPDATE relation_expr_opt_alias
 | 
			
		||||
					n->returningList = $7;
 | 
			
		||||
					$$ = (Node *)n;
 | 
			
		||||
				}
 | 
			
		||||
            | UPDATE relation_expr_opt_alias
 | 
			
		||||
			SET update_target_lists_list
 | 
			
		||||
			from_clause
 | 
			
		||||
			where_clause
 | 
			
		||||
			returning_clause
 | 
			
		||||
				{
 | 
			
		||||
					UpdateStmt *n = makeNode(UpdateStmt);
 | 
			
		||||
					n->relation = $2;
 | 
			
		||||
					n->targetList = $4;
 | 
			
		||||
					n->fromClause = $5;
 | 
			
		||||
					n->whereClause = $6;
 | 
			
		||||
					n->returningList = $7;
 | 
			
		||||
					$$ = (Node *)n;
 | 
			
		||||
				}
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -5941,6 +5957,60 @@ values_item:
 | 
			
		||||
			| DEFAULT				{ $$ = (Node *) makeNode(SetToDefault); }
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
update_target_lists_list:
 | 
			
		||||
			update_target_lists_el { $$ = $1; }
 | 
			
		||||
			| update_target_lists_list ',' update_target_lists_el { $$ = list_concat($1, $3); }
 | 
			
		||||
		;
 | 
			
		||||
		
 | 
			
		||||
update_target_lists_el:
 | 
			
		||||
			'(' update_col_list ')' '=' '(' update_value_list ')'
 | 
			
		||||
				{
 | 
			
		||||
					ListCell *col_cell;
 | 
			
		||||
					ListCell *val_cell;
 | 
			
		||||
 | 
			
		||||
					if (list_length($2) != list_length($6))
 | 
			
		||||
					{
 | 
			
		||||
						ereport(ERROR, 
 | 
			
		||||
							(errcode(ERRCODE_SYNTAX_ERROR),
 | 
			
		||||
							 errmsg("number of columns does not match to number of values")));
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					for (col_cell = list_head($2), val_cell = list_head($6);
 | 
			
		||||
						 col_cell != NULL && val_cell != NULL;
 | 
			
		||||
						 col_cell = lnext(col_cell), val_cell = lnext(val_cell))
 | 
			
		||||
					{
 | 
			
		||||
						/* merge update_value_list with update_col_list */
 | 
			
		||||
						ResTarget *res_col = (ResTarget *) lfirst(col_cell);
 | 
			
		||||
						ResTarget *res_val = (ResTarget *) lfirst(val_cell);
 | 
			
		||||
 | 
			
		||||
						res_col->val = (Node *)copyObject(res_val);
 | 
			
		||||
					}
 | 
			
		||||
				    
 | 
			
		||||
					$$ = $2;
 | 
			
		||||
				}
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
update_col_list:
 | 
			
		||||
			update_col_list_el { $$ = list_make1($1); }
 | 
			
		||||
			| update_col_list ',' update_col_list_el { $$ = lappend($1, $3); }
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
update_col_list_el:
 | 
			
		||||
			ColId opt_indirection
 | 
			
		||||
				{
 | 
			
		||||
					$$ = makeNode(ResTarget);
 | 
			
		||||
					$$->name = $1;
 | 
			
		||||
					$$->indirection = $2;
 | 
			
		||||
					$$->val = NULL;
 | 
			
		||||
					$$->location = @1;
 | 
			
		||||
				}
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
update_value_list:
 | 
			
		||||
			values_item { $$ = list_make1($1); }
 | 
			
		||||
			| update_value_list ',' values_item { $$ = lappend($1, $3); }
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user