diff --git a/doc/src/sgml/ref/alter_view.sgml b/doc/src/sgml/ref/alter_view.sgml
index 2e9edc1975..b66160bfb8 100644
*** a/doc/src/sgml/ref/alter_view.sgml
--- b/doc/src/sgml/ref/alter_view.sgml
***************
*** 24,29 **** PostgreSQL documentation
--- 24,30 ----
  ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> SET DEFAULT <replaceable class="parameter">expression</replaceable>
  ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> DROP DEFAULT
  ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
+ ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME [ COLUMN ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
  ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
  ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
  ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">view_option_name</replaceable> [= <replaceable class="parameter">view_option_value</replaceable>] [, ... ] )
***************
*** 65,70 **** ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RESET
--- 66,89 ----
      </listitem>
     </varlistentry>
  
+    <varlistentry>
+     <term><replaceable class="parameter">column_name</replaceable></term>
+     <listitem>
+      <para>
+       Name of an existing column.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><replaceable class="parameter">new_column_name</replaceable></term>
+     <listitem>
+      <para>
+       New name for an existing column.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
     <varlistentry>
      <term><literal>IF EXISTS</literal></term>
      <listitem>
diff --git a/src/backend/commands/view.index bea890f177..1b4d66dcd9 100644
*** a/src/backend/commands/view.c
--- b/src/backend/commands/view.c
***************
*** 277,283 **** checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc)
  					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
  					 errmsg("cannot change name of view column \"%s\" to \"%s\"",
  							NameStr(oldattr->attname),
! 							NameStr(newattr->attname))));
  		/* XXX would it be safe to allow atttypmod to change?  Not sure */
  		if (newattr->atttypid != oldattr->atttypid ||
  			newattr->atttypmod != oldattr->atttypmod)
--- 277,284 ----
  					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
  					 errmsg("cannot change name of view column \"%s\" to \"%s\"",
  							NameStr(oldattr->attname),
! 							NameStr(newattr->attname)),
! 					 errhint("Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead.")));
  		/* XXX would it be safe to allow atttypmod to change?  Not sure */
  		if (newattr->atttypid != oldattr->atttypid ||
  			newattr->atttypmod != oldattr->atttypmod)
diff --git a/src/backend/parser/grindex 3f67aaf30e..18e4d7636a 100644
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 8775,8780 **** RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
--- 8775,8802 ----
  					n->missing_ok = true;
  					$$ = (Node *)n;
  				}
+ 			| ALTER VIEW qualified_name RENAME opt_column name TO name
+ 				{
+ 					RenameStmt *n = makeNode(RenameStmt);
+ 					n->renameType = OBJECT_COLUMN;
+ 					n->relationType = OBJECT_VIEW;
+ 					n->relation = $3;
+ 					n->subname = $6;
+ 					n->newname = $8;
+ 					n->missing_ok = false;
+ 					$$ = (Node *)n;
+ 				}
+ 			| ALTER VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name
+ 				{
+ 					RenameStmt *n = makeNode(RenameStmt);
+ 					n->renameType = OBJECT_COLUMN;
+ 					n->relationType = OBJECT_VIEW;
+ 					n->relation = $5;
+ 					n->subname = $8;
+ 					n->newname = $10;
+ 					n->missing_ok = true;
+ 					$$ = (Node *)n;
+ 				}
  			| ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name
  				{
  					RenameStmt *n = makeNode(RenameStmt);
diff --git a/src/bin/psql/tab-coindex 2b1e3cda4a..2837939e93 100644
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
***************
*** 1797,1804 **** psql_completion(const char *text, int start, int end)
  		COMPLETE_WITH("TO");
  	/* ALTER VIEW <name> */
  	else if (Matches("ALTER", "VIEW", MatchAny))
! 		COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO",
  					  "SET SCHEMA");
  	/* ALTER MATERIALIZED VIEW <name> */
  	else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
  		COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO",
--- 1797,1816 ----
  		COMPLETE_WITH("TO");
  	/* ALTER VIEW <name> */
  	else if (Matches("ALTER", "VIEW", MatchAny))
! 		COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME",
  					  "SET SCHEMA");
+ 	/* ALTER VIEW xxx RENAME */
+ 	else if (Matches("ALTER", "VIEW", MatchAny, "RENAME"))
+ 		COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'TO'");
+ 	else if (Matches("ALTER", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
+ 		COMPLETE_WITH_ATTR(prev3_wd, "");
+ 	/* ALTER VIEW xxx RENAME yyy */
+ 	else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
+ 		COMPLETE_WITH("TO");
+ 	/* ALTER VIEW xxx RENAME COLUMN yyy */
+ 	else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
+ 		COMPLETE_WITH("TO");
+ 
  	/* ALTER MATERIALIZED VIEW <name> */
  	else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
  		COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO",
diff --git a/src/test/regress/expeindex 2fd36ca9a1..9a92629fd7 100644
*** a/src/test/regress/expected/create_view.out
--- b/src/test/regress/expected/create_view.out
***************
*** 64,69 **** ERROR:  cannot drop columns from view
--- 64,70 ----
  CREATE OR REPLACE VIEW viewtest AS
  	SELECT 1, * FROM viewtest_tbl;
  ERROR:  cannot change name of view column "a" to "?column?"
+ HINT:  Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead.
  -- should fail
  CREATE OR REPLACE VIEW viewtest AS
  	SELECT a, b::numeric FROM viewtest_tbl;
***************
*** 1189,1194 **** select pg_get_viewdef('vv1', true);
--- 1190,1218 ----
        CROSS JOIN tt6) j(aa, bb, cc_1, cc, dd);
  (1 row)
  
+ create view v4 as select * from v1;
+ alter view v1 rename column a to x;
+ select pg_get_viewdef('v1', true);
+                   pg_get_viewdef                   
+ ---------------------------------------------------
+   SELECT tt2.b,                                   +
+      tt3.c,                                       +
+      tt2.a AS x,                                  +
+      tt3.ax                                       +
+     FROM tt2                                      +
+       JOIN tt3 tt3(ax, b, c, c_1, e) USING (b, c);
+ (1 row)
+ 
+ select pg_get_viewdef('v4', true);
+  pg_get_viewdef 
+ ----------------
+   SELECT v1.b, +
+      v1.c,     +
+      v1.x AS a,+
+      v1.ax     +
+     FROM v1;
+ (1 row)
+ 
  -- Unnamed FULL JOIN USING is lots of fun too
  create table tt7 (x int, xx int, y int);
  alter table tt7 drop column xx;
***************
*** 1782,1788 **** drop cascades to view aliased_view_2
  drop cascades to view aliased_view_3
  drop cascades to view aliased_view_4
  DROP SCHEMA testviewschm2 CASCADE;
! NOTICE:  drop cascades to 63 other objects
  DETAIL:  drop cascades to table t1
  drop cascades to view temporal1
  drop cascades to view temporal2
--- 1806,1812 ----
  drop cascades to view aliased_view_3
  drop cascades to view aliased_view_4
  DROP SCHEMA testviewschm2 CASCADE;
! NOTICE:  drop cascades to 64 other objects
  DETAIL:  drop cascades to table t1
  drop cascades to view temporal1
  drop cascades to view temporal2
***************
*** 1818,1823 **** drop cascades to view v3
--- 1842,1848 ----
  drop cascades to table tt5
  drop cascades to table tt6
  drop cascades to view vv1
+ drop cascades to view v4
  drop cascades to table tt7
  drop cascades to table tt8
  drop cascades to view vv2
diff --git a/src/test/regress/sql/create_view.sqindex 8c0f45cc52..be5d90727a 100644
*** a/src/test/regress/sql/create_view.sql
--- b/src/test/regress/sql/create_view.sql
***************
*** 391,396 **** select pg_get_viewdef('vv1', true);
--- 391,402 ----
  alter table tt5 drop column c;
  select pg_get_viewdef('vv1', true);
  
+ create view v4 as select * from v1;
+ alter view v1 rename column a to x;
+ select pg_get_viewdef('v1', true);
+ select pg_get_viewdef('v4', true);
+ 
+ 
  -- Unnamed FULL JOIN USING is lots of fun too
  
  create table tt7 (x int, xx int, y int);
