FabrÃzio de Royes Mello reviewed by Rushabh Lathia.
 
  <refsynopsisdiv>
 <synopsis>
-CREATE MATERIALIZED VIEW <replaceable>table_name</replaceable>
+CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] <replaceable>table_name</replaceable>
     [ (<replaceable>column_name</replaceable> [, ...] ) ]
     [ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
     [ TABLESPACE <replaceable class="PARAMETER">tablespace_name</replaceable> ]
  <refsect1>
   <title>Parameters</title>
 
+   <varlistentry>
+    <term><literal>IF NOT EXISTS</></term>
+    <listitem>
+     <para>
+      Do not throw an error if a materialized view with the same name already
+      exists. A notice is issued in this case.  Note that there is no guarantee
+      that the existing materialized view is anything like the one that would
+      have been created.
+     </para>
+    </listitem>
+   </varlistentry>
+
   <variablelist>
    <varlistentry>
     <term><replaceable>table_name</replaceable></term>
 
 
  <refsynopsisdiv>
 <synopsis>
-CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE <replaceable>table_name</replaceable>
+CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] <replaceable>table_name</replaceable>
     [ (<replaceable>column_name</replaceable> [, ...] ) ]
     [ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
     [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>IF NOT EXISTS</></term>
+    <listitem>
+     <para>
+      Do not throw an error if a relation with the same name already exists.
+      A notice is issued in this case. Refer to <xref linkend="sql-createtable">
+      for details.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><replaceable>table_name</replaceable></term>
     <listitem>
 
 #include "access/sysattr.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "catalog/namespace.h"
 #include "catalog/toasting.h"
 #include "commands/createas.h"
 #include "commands/matview.h"
    QueryDesc  *queryDesc;
    ScanDirection dir;
 
+   if (stmt->if_not_exists)
+   {
+       Oid nspid;
+
+       nspid = RangeVarGetCreationNamespace(stmt->into->rel);
+
+       if (get_relname_relid(stmt->into->rel->relname, nspid))
+       {
+           ereport(NOTICE,
+                   (errcode(ERRCODE_DUPLICATE_TABLE),
+                    errmsg("relation \"%s\" already exists, skipping",
+                           stmt->into->rel->relname)));
+           return InvalidOid;
+       }
+   }
+
    /*
     * Create the tuple receiver object and insert info it will need
     */
 
    COPY_NODE_FIELD(into);
    COPY_SCALAR_FIELD(relkind);
    COPY_SCALAR_FIELD(is_select_into);
+   COPY_SCALAR_FIELD(if_not_exists);
 
    return newnode;
 }
 
    COMPARE_NODE_FIELD(into);
    COMPARE_SCALAR_FIELD(relkind);
    COMPARE_SCALAR_FIELD(is_select_into);
+   COMPARE_SCALAR_FIELD(if_not_exists);
 
    return true;
 }
 
                    ctas->into = $4;
                    ctas->relkind = OBJECT_TABLE;
                    ctas->is_select_into = false;
+                   ctas->if_not_exists = false;
                    /* cram additional flags into the IntoClause */
                    $4->rel->relpersistence = $2;
                    $4->skipData = !($7);
                    $$ = (Node *) ctas;
                }
+       | CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS SelectStmt opt_with_data
+               {
+                   CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
+                   ctas->query = $9;
+                   ctas->into = $7;
+                   ctas->relkind = OBJECT_TABLE;
+                   ctas->is_select_into = false;
+                   ctas->if_not_exists = true;
+                   /* cram additional flags into the IntoClause */
+                   $7->rel->relpersistence = $2;
+                   $7->skipData = !($10);
+                   $$ = (Node *) ctas;
+               }
        ;
 
 create_as_target:
                    ctas->into = $5;
                    ctas->relkind = OBJECT_MATVIEW;
                    ctas->is_select_into = false;
+                   ctas->if_not_exists = false;
                    /* cram additional flags into the IntoClause */
                    $5->rel->relpersistence = $2;
                    $5->skipData = !($8);
                    $$ = (Node *) ctas;
                }
+       | CREATE OptNoLog MATERIALIZED VIEW IF_P NOT EXISTS create_mv_target AS SelectStmt opt_with_data
+               {
+                   CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
+                   ctas->query = $10;
+                   ctas->into = $8;
+                   ctas->relkind = OBJECT_MATVIEW;
+                   ctas->is_select_into = false;
+                   ctas->if_not_exists = true;
+                   /* cram additional flags into the IntoClause */
+                   $8->rel->relpersistence = $2;
+                   $8->skipData = !($11);
+                   $$ = (Node *) ctas;
+               }
        ;
 
 create_mv_target:
 
    IntoClause *into;           /* destination table */
    ObjectType  relkind;        /* OBJECT_TABLE or OBJECT_MATVIEW */
    bool        is_select_into; /* it was written as SELECT INTO */
+   bool        if_not_exists;  /* just do nothing if it already exists? */
 } CreateTableAsStmt;
 
 /* ----------------------
 
 CREATE TEMP TABLE public.temp_to_perm (a int primary key);     -- not OK
 ERROR:  cannot create temporary relation in non-temporary schema
 DROP TABLE unlogged1, public.unlogged2;
+CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
+CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
+ERROR:  relation "as_select1" already exists
+CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
+NOTICE:  relation "as_select1" already exists, skipping
+DROP TABLE as_select1;
 
 CREATE TABLE foo_data AS SELECT i, md5(random()::text)
   FROM generate_series(1, 10) i;
 CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
+CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
+ERROR:  relation "mv_foo" already exists
+CREATE MATERIALIZED VIEW IF NOT EXISTS mv_foo AS SELECT * FROM foo_data;
+NOTICE:  relation "mv_foo" already exists, skipping
 CREATE UNIQUE INDEX ON mv_foo (i);
 RESET ROLE;
 REFRESH MATERIALIZED VIEW mv_foo;
 
 CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key);     -- also OK
 CREATE TEMP TABLE public.temp_to_perm (a int primary key);     -- not OK
 DROP TABLE unlogged1, public.unlogged2;
+
+CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
+CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
+CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
+DROP TABLE as_select1;
 
 CREATE TABLE foo_data AS SELECT i, md5(random()::text)
   FROM generate_series(1, 10) i;
 CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
+CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
+CREATE MATERIALIZED VIEW IF NOT EXISTS mv_foo AS SELECT * FROM foo_data;
 CREATE UNIQUE INDEX ON mv_foo (i);
 RESET ROLE;
 REFRESH MATERIALIZED VIEW mv_foo;