summaryrefslogtreecommitdiffstats
path: root/doc/src/sgml/html/sql-createview.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/sgml/html/sql-createview.html')
-rw-r--r--doc/src/sgml/html/sql-createview.html346
1 files changed, 346 insertions, 0 deletions
diff --git a/doc/src/sgml/html/sql-createview.html b/doc/src/sgml/html/sql-createview.html
new file mode 100644
index 0000000..ea1819e
--- /dev/null
+++ b/doc/src/sgml/html/sql-createview.html
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>CREATE VIEW</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="sql-createusermapping.html" title="CREATE USER MAPPING" /><link rel="next" href="sql-deallocate.html" title="DEALLOCATE" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">CREATE VIEW</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="sql-createusermapping.html" title="CREATE USER MAPPING">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="sql-commands.html" title="SQL Commands">Up</a></td><th width="60%" align="center">SQL Commands</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 15.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="sql-deallocate.html" title="DEALLOCATE">Next</a></td></tr></table><hr /></div><div class="refentry" id="SQL-CREATEVIEW"><div class="titlepage"></div><a id="id-1.9.3.97.1" class="indexterm"></a><div class="refnamediv"><h2><span class="refentrytitle">CREATE VIEW</span></h2><p>CREATE VIEW — define a new view</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><pre class="synopsis">
+CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEW <em class="replaceable"><code>name</code></em> [ ( <em class="replaceable"><code>column_name</code></em> [, ...] ) ]
+ [ WITH ( <em class="replaceable"><code>view_option_name</code></em> [= <em class="replaceable"><code>view_option_value</code></em>] [, ... ] ) ]
+ AS <em class="replaceable"><code>query</code></em>
+ [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
+</pre></div><div class="refsect1" id="id-1.9.3.97.5"><h2>Description</h2><p>
+ <code class="command">CREATE VIEW</code> defines a view of a query. The view
+ is not physically materialized. Instead, the query is run every time
+ the view is referenced in a query.
+ </p><p>
+ <code class="command">CREATE OR REPLACE VIEW</code> is similar, but if a view
+ of the same name already exists, it is replaced. The new query must
+ generate the same columns that were generated by the existing view query
+ (that is, the same column names in the same order and with the same data
+ types), but it may add additional columns to the end of the list. The
+ calculations giving rise to the output columns may be completely different.
+ </p><p>
+ If a schema name is given (for example, <code class="literal">CREATE VIEW
+ myschema.myview ...</code>) then the view is created in the specified
+ schema. Otherwise it is created in the current schema. Temporary
+ views exist in a special schema, so a schema name cannot be given
+ when creating a temporary view. The name of the view must be
+ distinct from the name of any other relation (table, sequence, index, view,
+ materialized view, or foreign table) in the same schema.
+ </p></div><div class="refsect1" id="id-1.9.3.97.6"><h2>Parameters</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal">TEMPORARY</code> or <code class="literal">TEMP</code></span></dt><dd><p>
+ If specified, the view is created as a temporary view.
+ Temporary views are automatically dropped at the end of the
+ current session. Existing
+ permanent relations with the same name are not visible to the
+ current session while the temporary view exists, unless they are
+ referenced with schema-qualified names.
+ </p><p>
+ If any of the tables referenced by the view are temporary,
+ the view is created as a temporary view (whether
+ <code class="literal">TEMPORARY</code> is specified or not).
+ </p></dd><dt><span class="term"><code class="literal">RECURSIVE</code>
+ <a id="id-1.9.3.97.6.2.2.1.2" class="indexterm"></a>
+ </span></dt><dd><p>
+ Creates a recursive view. The syntax
+</p><pre class="synopsis">
+CREATE RECURSIVE VIEW [ <em class="replaceable"><code>schema</code></em> . ] <em class="replaceable"><code>view_name</code></em> (<em class="replaceable"><code>column_names</code></em>) AS SELECT <em class="replaceable"><code>...</code></em>;
+</pre><p>
+ is equivalent to
+</p><pre class="synopsis">
+CREATE VIEW [ <em class="replaceable"><code>schema</code></em> . ] <em class="replaceable"><code>view_name</code></em> AS WITH RECURSIVE <em class="replaceable"><code>view_name</code></em> (<em class="replaceable"><code>column_names</code></em>) AS (SELECT <em class="replaceable"><code>...</code></em>) SELECT <em class="replaceable"><code>column_names</code></em> FROM <em class="replaceable"><code>view_name</code></em>;
+</pre><p>
+ A view column name list must be specified for a recursive view.
+ </p></dd><dt><span class="term"><em class="replaceable"><code>name</code></em></span></dt><dd><p>
+ The name (optionally schema-qualified) of a view to be created.
+ </p></dd><dt><span class="term"><em class="replaceable"><code>column_name</code></em></span></dt><dd><p>
+ An optional list of names to be used for columns of the view.
+ If not given, the column names are deduced from the query.
+ </p></dd><dt><span class="term"><code class="literal">WITH ( <em class="replaceable"><code>view_option_name</code></em> [= <em class="replaceable"><code>view_option_value</code></em>] [, ... ] )</code></span></dt><dd><p>
+ This clause specifies optional parameters for a view; the following
+ parameters are supported:
+
+ </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal">check_option</code> (<code class="type">enum</code>)</span></dt><dd><p>
+ This parameter may be either <code class="literal">local</code> or
+ <code class="literal">cascaded</code>, and is equivalent to specifying
+ <code class="literal">WITH [ CASCADED | LOCAL ] CHECK OPTION</code> (see below).
+ </p></dd><dt><span class="term"><code class="literal">security_barrier</code> (<code class="type">boolean</code>)</span></dt><dd><p>
+ This should be used if the view is intended to provide row-level
+ security. See <a class="xref" href="rules-privileges.html" title="41.5. Rules and Privileges">Section 41.5</a> for full details.
+ </p></dd><dt><span class="term"><code class="literal">security_invoker</code> (<code class="type">boolean</code>)</span></dt><dd><p>
+ This option causes the underlying base relations to be checked
+ against the privileges of the user of the view rather than the view
+ owner. See the notes below for full details.
+ </p></dd></dl></div><p>
+
+ All of the above options can be changed on existing views using <a class="link" href="sql-alterview.html" title="ALTER VIEW"><code class="command">ALTER VIEW</code></a>.
+ </p></dd><dt><span class="term"><em class="replaceable"><code>query</code></em></span></dt><dd><p>
+ A <a class="link" href="sql-select.html" title="SELECT"><code class="command">SELECT</code></a> or
+ <a class="link" href="sql-values.html" title="VALUES"><code class="command">VALUES</code></a> command
+ which will provide the columns and rows of the view.
+ </p></dd><dt><span class="term"><code class="literal">WITH [ CASCADED | LOCAL ] CHECK OPTION</code>
+ <a id="id-1.9.3.97.6.2.7.1.2" class="indexterm"></a>
+ <a id="id-1.9.3.97.6.2.7.1.3" class="indexterm"></a>
+ </span></dt><dd><p>
+ This option controls the behavior of automatically updatable views. When
+ this option is specified, <code class="command">INSERT</code> and <code class="command">UPDATE</code>
+ commands on the view will be checked to ensure that new rows satisfy the
+ view-defining condition (that is, the new rows are checked to ensure that
+ they are visible through the view). If they are not, the update will be
+ rejected. If the <code class="literal">CHECK OPTION</code> is not specified,
+ <code class="command">INSERT</code> and <code class="command">UPDATE</code> commands on the view are
+ allowed to create rows that are not visible through the view. The
+ following check options are supported:
+
+ </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal">LOCAL</code></span></dt><dd><p>
+ New rows are only checked against the conditions defined directly in
+ the view itself. Any conditions defined on underlying base views are
+ not checked (unless they also specify the <code class="literal">CHECK OPTION</code>).
+ </p></dd><dt><span class="term"><code class="literal">CASCADED</code></span></dt><dd><p>
+ New rows are checked against the conditions of the view and all
+ underlying base views. If the <code class="literal">CHECK OPTION</code> is specified,
+ and neither <code class="literal">LOCAL</code> nor <code class="literal">CASCADED</code> is specified,
+ then <code class="literal">CASCADED</code> is assumed.
+ </p></dd></dl></div><p>
+ </p><p>
+ The <code class="literal">CHECK OPTION</code> may not be used with <code class="literal">RECURSIVE</code>
+ views.
+ </p><p>
+ Note that the <code class="literal">CHECK OPTION</code> is only supported on views that
+ are automatically updatable, and do not have <code class="literal">INSTEAD OF</code>
+ triggers or <code class="literal">INSTEAD</code> rules. If an automatically updatable
+ view is defined on top of a base view that has <code class="literal">INSTEAD OF</code>
+ triggers, then the <code class="literal">LOCAL CHECK OPTION</code> may be used to check
+ the conditions on the automatically updatable view, but the conditions
+ on the base view with <code class="literal">INSTEAD OF</code> triggers will not be
+ checked (a cascaded check option will not cascade down to a
+ trigger-updatable view, and any check options defined directly on a
+ trigger-updatable view will be ignored). If the view or any of its base
+ relations has an <code class="literal">INSTEAD</code> rule that causes the
+ <code class="command">INSERT</code> or <code class="command">UPDATE</code> command to be rewritten, then
+ all check options will be ignored in the rewritten query, including any
+ checks from automatically updatable views defined on top of the relation
+ with the <code class="literal">INSTEAD</code> rule.
+ </p></dd></dl></div></div><div class="refsect1" id="id-1.9.3.97.7"><h2>Notes</h2><p>
+ Use the <a class="link" href="sql-dropview.html" title="DROP VIEW"><code class="command">DROP VIEW</code></a>
+ statement to drop views.
+ </p><p>
+ Be careful that the names and types of the view's columns will be
+ assigned the way you want. For example:
+</p><pre class="programlisting">
+CREATE VIEW vista AS SELECT 'Hello World';
+</pre><p>
+ is bad form because the column name defaults to <code class="literal">?column?</code>;
+ also, the column data type defaults to <code class="type">text</code>, which might not
+ be what you wanted. Better style for a string literal in a view's
+ result is something like:
+</p><pre class="programlisting">
+CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
+</pre><p>
+ </p><p>
+ By default, access to the underlying base relations referenced in the view
+ is determined by the permissions of the view owner. In some cases, this
+ can be used to provide secure but restricted access to the underlying
+ tables. However, not all views are secure against tampering; see <a class="xref" href="rules-privileges.html" title="41.5. Rules and Privileges">Section 41.5</a> for details.
+ </p><p>
+ If the view has the <code class="literal">security_invoker</code> property set to
+ <code class="literal">true</code>, access to the underlying base relations is
+ determined by the permissions of the user executing the query, rather than
+ the view owner. Thus, the user of a security invoker view must have the
+ relevant permissions on the view and its underlying base relations.
+ </p><p>
+ If any of the underlying base relations is a security invoker view, it
+ will be treated as if it had been accessed directly from the original
+ query. Thus, a security invoker view will always check its underlying
+ base relations using the permissions of the current user, even if it is
+ accessed from a view without the <code class="literal">security_invoker</code>
+ property.
+ </p><p>
+ If any of the underlying base relations has
+ <a class="link" href="ddl-rowsecurity.html" title="5.8. Row Security Policies">row-level security</a> enabled, then
+ by default, the row-level security policies of the view owner are applied,
+ and access to any additional relations referred to by those policies is
+ determined by the permissions of the view owner. However, if the view has
+ <code class="literal">security_invoker</code> set to <code class="literal">true</code>, then
+ the policies and permissions of the invoking user are used instead, as if
+ the base relations had been referenced directly from the query using the
+ view.
+ </p><p>
+ Functions called in the view are treated the same as if they had been
+ called directly from the query using the view. Therefore, the user of
+ a view must have permissions to call all functions used by the view.
+ Functions in the view are executed with the privileges of the user
+ executing the query or the function owner, depending on whether the
+ functions are defined as <code class="literal">SECURITY INVOKER</code> or
+ <code class="literal">SECURITY DEFINER</code>. Thus, for example, calling
+ <code class="literal">CURRENT_USER</code> directly in a view will always return the
+ invoking user, not the view owner. This is not affected by the view's
+ <code class="literal">security_invoker</code> setting, and so a view with
+ <code class="literal">security_invoker</code> set to <code class="literal">false</code> is
+ <span class="emphasis"><em>not</em></span> equivalent to a
+ <code class="literal">SECURITY DEFINER</code> function and those concepts should not
+ be confused.
+ </p><p>
+ The user creating or replacing a view must have <code class="literal">USAGE</code>
+ privileges on any schemas referred to in the view query, in order to look
+ up the referenced objects in those schemas. Note, however, that this
+ lookup only happens when the view is created or replaced. Therefore, the
+ user of the view only requires the <code class="literal">USAGE</code> privilege on
+ the schema containing the view, not on the schemas referred to in the view
+ query, even for a security invoker view.
+ </p><p>
+ When <code class="command">CREATE OR REPLACE VIEW</code> is used on an existing
+ view, only the view's defining SELECT rule, plus any
+ <code class="literal">WITH ( ... )</code> parameters and its
+ <code class="literal">CHECK OPTION</code> are changed.
+ Other view properties, including ownership, permissions, and non-SELECT
+ rules, remain unchanged. You must own the view
+ to replace it (this includes being a member of the owning role).
+ </p><div class="refsect2" id="SQL-CREATEVIEW-UPDATABLE-VIEWS"><h3>Updatable Views</h3><a id="id-1.9.3.97.7.11.2" class="indexterm"></a><p>
+ Simple views are automatically updatable: the system will allow
+ <code class="command">INSERT</code>, <code class="command">UPDATE</code> and <code class="command">DELETE</code> statements
+ to be used on the view in the same way as on a regular table. A view is
+ automatically updatable if it satisfies all of the following conditions:
+
+ </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
+ The view must have exactly one entry in its <code class="literal">FROM</code> list,
+ which must be a table or another updatable view.
+ </p></li><li class="listitem"><p>
+ The view definition must not contain <code class="literal">WITH</code>,
+ <code class="literal">DISTINCT</code>, <code class="literal">GROUP BY</code>, <code class="literal">HAVING</code>,
+ <code class="literal">LIMIT</code>, or <code class="literal">OFFSET</code> clauses at the top level.
+ </p></li><li class="listitem"><p>
+ The view definition must not contain set operations (<code class="literal">UNION</code>,
+ <code class="literal">INTERSECT</code> or <code class="literal">EXCEPT</code>) at the top level.
+ </p></li><li class="listitem"><p>
+ The view's select list must not contain any aggregates, window functions
+ or set-returning functions.
+ </p></li></ul></div><p>
+ </p><p>
+ An automatically updatable view may contain a mix of updatable and
+ non-updatable columns. A column is updatable if it is a simple reference
+ to an updatable column of the underlying base relation; otherwise the
+ column is read-only, and an error will be raised if an <code class="command">INSERT</code>
+ or <code class="command">UPDATE</code> statement attempts to assign a value to it.
+ </p><p>
+ If the view is automatically updatable the system will convert any
+ <code class="command">INSERT</code>, <code class="command">UPDATE</code> or <code class="command">DELETE</code> statement
+ on the view into the corresponding statement on the underlying base
+ relation. <code class="command">INSERT</code> statements that have an <code class="literal">ON
+ CONFLICT UPDATE</code> clause are fully supported.
+ </p><p>
+ If an automatically updatable view contains a <code class="literal">WHERE</code>
+ condition, the condition restricts which rows of the base relation are
+ available to be modified by <code class="command">UPDATE</code> and <code class="command">DELETE</code>
+ statements on the view. However, an <code class="command">UPDATE</code> is allowed to
+ change a row so that it no longer satisfies the <code class="literal">WHERE</code>
+ condition, and thus is no longer visible through the view. Similarly,
+ an <code class="command">INSERT</code> command can potentially insert base-relation rows
+ that do not satisfy the <code class="literal">WHERE</code> condition and thus are not
+ visible through the view (<code class="literal">ON CONFLICT UPDATE</code> may
+ similarly affect an existing row not visible through the view).
+ The <code class="literal">CHECK OPTION</code> may be used to prevent
+ <code class="command">INSERT</code> and <code class="command">UPDATE</code> commands from creating
+ such rows that are not visible through the view.
+ </p><p>
+ If an automatically updatable view is marked with the
+ <code class="literal">security_barrier</code> property then all the view's <code class="literal">WHERE</code>
+ conditions (and any conditions using operators which are marked as <code class="literal">LEAKPROOF</code>)
+ will always be evaluated before any conditions that a user of the view has
+ added. See <a class="xref" href="rules-privileges.html" title="41.5. Rules and Privileges">Section 41.5</a> for full details. Note that,
+ due to this, rows which are not ultimately returned (because they do not
+ pass the user's <code class="literal">WHERE</code> conditions) may still end up being locked.
+ <code class="command">EXPLAIN</code> can be used to see which conditions are
+ applied at the relation level (and therefore do not lock rows) and which are
+ not.
+ </p><p>
+ A more complex view that does not satisfy all these conditions is
+ read-only by default: the system will not allow an insert, update, or
+ delete on the view. You can get the effect of an updatable view by
+ creating <code class="literal">INSTEAD OF</code> triggers on the view, which must
+ convert attempted inserts, etc. on the view into appropriate actions
+ on other tables. For more information see <a class="xref" href="sql-createtrigger.html" title="CREATE TRIGGER"><span class="refentrytitle">CREATE TRIGGER</span></a>. Another possibility is to create rules
+ (see <a class="xref" href="sql-createrule.html" title="CREATE RULE"><span class="refentrytitle">CREATE RULE</span></a>), but in practice triggers are
+ easier to understand and use correctly.
+ </p><p>
+ Note that the user performing the insert, update or delete on the view
+ must have the corresponding insert, update or delete privilege on the
+ view. In addition, by default, the view's owner must have the relevant
+ privileges on the underlying base relations, whereas the user performing
+ the update does not need any permissions on the underlying base relations
+ (see <a class="xref" href="rules-privileges.html" title="41.5. Rules and Privileges">Section 41.5</a>). However, if the view has
+ <code class="literal">security_invoker</code> set to <code class="literal">true</code>, the
+ user performing the update, rather than the view owner, must have the
+ relevant privileges on the underlying base relations.
+ </p></div></div><div class="refsect1" id="id-1.9.3.97.8"><h2>Examples</h2><p>
+ Create a view consisting of all comedy films:
+
+</p><pre class="programlisting">
+CREATE VIEW comedies AS
+ SELECT *
+ FROM films
+ WHERE kind = 'Comedy';
+</pre><p>
+ This will create a view containing the columns that are in the
+ <code class="literal">film</code> table at the time of view creation. Though
+ <code class="literal">*</code> was used to create the view, columns added later to
+ the table will not be part of the view.
+ </p><p>
+ Create a view with <code class="literal">LOCAL CHECK OPTION</code>:
+
+</p><pre class="programlisting">
+CREATE VIEW universal_comedies AS
+ SELECT *
+ FROM comedies
+ WHERE classification = 'U'
+ WITH LOCAL CHECK OPTION;
+</pre><p>
+ This will create a view based on the <code class="literal">comedies</code> view, showing
+ only films with <code class="literal">kind = 'Comedy'</code> and
+ <code class="literal">classification = 'U'</code>. Any attempt to <code class="command">INSERT</code> or
+ <code class="command">UPDATE</code> a row in the view will be rejected if the new row
+ doesn't have <code class="literal">classification = 'U'</code>, but the film
+ <code class="literal">kind</code> will not be checked.
+ </p><p>
+ Create a view with <code class="literal">CASCADED CHECK OPTION</code>:
+
+</p><pre class="programlisting">
+CREATE VIEW pg_comedies AS
+ SELECT *
+ FROM comedies
+ WHERE classification = 'PG'
+ WITH CASCADED CHECK OPTION;
+</pre><p>
+ This will create a view that checks both the <code class="literal">kind</code> and
+ <code class="literal">classification</code> of new rows.
+ </p><p>
+ Create a view with a mix of updatable and non-updatable columns:
+
+</p><pre class="programlisting">
+CREATE VIEW comedies AS
+ SELECT f.*,
+ country_code_to_name(f.country_code) AS country,
+ (SELECT avg(r.rating)
+ FROM user_ratings r
+ WHERE r.film_id = f.id) AS avg_rating
+ FROM films f
+ WHERE f.kind = 'Comedy';
+</pre><p>
+ This view will support <code class="command">INSERT</code>, <code class="command">UPDATE</code> and
+ <code class="command">DELETE</code>. All the columns from the <code class="literal">films</code> table will
+ be updatable, whereas the computed columns <code class="literal">country</code> and
+ <code class="literal">avg_rating</code> will be read-only.
+ </p><p>
+ Create a recursive view consisting of the numbers from 1 to 100:
+</p><pre class="programlisting">
+CREATE RECURSIVE VIEW public.nums_1_100 (n) AS
+ VALUES (1)
+UNION ALL
+ SELECT n+1 FROM nums_1_100 WHERE n &lt; 100;
+</pre><p>
+ Notice that although the recursive view's name is schema-qualified in this
+ <code class="command">CREATE</code>, its internal self-reference is not schema-qualified.
+ This is because the implicitly-created CTE's name cannot be
+ schema-qualified.
+ </p></div><div class="refsect1" id="id-1.9.3.97.9"><h2>Compatibility</h2><p>
+ <code class="command">CREATE OR REPLACE VIEW</code> is a
+ <span class="productname">PostgreSQL</span> language extension.
+ So is the concept of a temporary view.
+ The <code class="literal">WITH ( ... )</code> clause is an extension as well, as are
+ security barrier views and security invoker views.
+ </p></div><div class="refsect1" id="id-1.9.3.97.10"><h2>See Also</h2><span class="simplelist"><a class="xref" href="sql-alterview.html" title="ALTER VIEW"><span class="refentrytitle">ALTER VIEW</span></a>, <a class="xref" href="sql-dropview.html" title="DROP VIEW"><span class="refentrytitle">DROP VIEW</span></a>, <a class="xref" href="sql-creatematerializedview.html" title="CREATE MATERIALIZED VIEW"><span class="refentrytitle">CREATE MATERIALIZED VIEW</span></a></span></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="sql-createusermapping.html" title="CREATE USER MAPPING">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="sql-commands.html" title="SQL Commands">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="sql-deallocate.html" title="DEALLOCATE">Next</a></td></tr><tr><td width="40%" align="left" valign="top">CREATE USER MAPPING </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 15.4 Documentation">Home</a></td><td width="40%" align="right" valign="top"> DEALLOCATE</td></tr></table></div></body></html> \ No newline at end of file