|
- <?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 POLICY</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 V1.79.1" /><link rel="prev" href="sql-createopfamily.html" title="CREATE OPERATOR FAMILY" /><link rel="next" href="sql-createprocedure.html" title="CREATE PROCEDURE" /></head><body><div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">CREATE POLICY</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="sql-createopfamily.html" title="CREATE OPERATOR FAMILY">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 12.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="sql-createprocedure.html" title="CREATE PROCEDURE">Next</a></td></tr></table><hr></hr></div><div class="refentry" id="SQL-CREATEPOLICY"><div class="titlepage"></div><a id="id-1.9.3.75.1" class="indexterm"></a><div class="refnamediv"><h2><span class="refentrytitle">CREATE POLICY</span></h2><p>CREATE POLICY — define a new row level security policy for a table</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><pre class="synopsis">
- CREATE POLICY <em class="replaceable"><code>name</code></em> ON <em class="replaceable"><code>table_name</code></em>
- [ AS { PERMISSIVE | RESTRICTIVE } ]
- [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
- [ TO { <em class="replaceable"><code>role_name</code></em> | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
- [ USING ( <em class="replaceable"><code>using_expression</code></em> ) ]
- [ WITH CHECK ( <em class="replaceable"><code>check_expression</code></em> ) ]
- </pre></div><div class="refsect1" id="id-1.9.3.75.5"><h2>Description</h2><p>
- The <code class="command">CREATE POLICY</code> command defines a new row-level
- security policy for a table. Note that row-level security must be
- enabled on the table (using <code class="command">ALTER TABLE ... ENABLE ROW LEVEL
- SECURITY</code>) in order for created policies to be applied.
- </p><p>
- A policy grants the permission to select, insert, update, or delete rows
- that match the relevant policy expression. Existing table rows are
- checked against the expression specified in <code class="literal">USING</code>,
- while new rows that would be created via <code class="literal">INSERT</code>
- or <code class="literal">UPDATE</code> are checked against the expression specified
- in <code class="literal">WITH CHECK</code>. When a <code class="literal">USING</code>
- expression returns true for a given row then that row is visible to the
- user, while if false or null is returned then the row is not visible.
- When a <code class="literal">WITH CHECK</code> expression returns true for a row
- then that row is inserted or updated, while if false or null is returned
- then an error occurs.
- </p><p>
- For <code class="command">INSERT</code> and <code class="command">UPDATE</code> statements,
- <code class="literal">WITH CHECK</code> expressions are enforced after
- <code class="literal">BEFORE</code> triggers are fired, and before any actual data
- modifications are made. Thus a <code class="literal">BEFORE ROW</code> trigger may
- modify the data to be inserted, affecting the result of the security
- policy check. <code class="literal">WITH CHECK</code> expressions are enforced
- before any other constraints.
- </p><p>
- Policy names are per-table. Therefore, one policy name can be used for many
- different tables and have a definition for each table which is appropriate to
- that table.
- </p><p>
- Policies can be applied for specific commands or for specific roles. The
- default for newly created policies is that they apply for all commands and
- roles, unless otherwise specified. Multiple policies may apply to a single
- command; see below for more details.
- <a class="xref" href="sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY" title="Table 256. Policies Applied by Command Type">Table 256</a> summarizes how the different types
- of policy apply to specific commands.
- </p><p>
- For policies that can have both <code class="literal">USING</code>
- and <code class="literal">WITH CHECK</code> expressions (<code class="literal">ALL</code>
- and <code class="literal">UPDATE</code>), if no <code class="literal">WITH CHECK</code>
- expression is defined, then the <code class="literal">USING</code> expression will be
- used both to determine which rows are visible (normal
- <code class="literal">USING</code> case) and which new rows will be allowed to be
- added (<code class="literal">WITH CHECK</code> case).
- </p><p>
- If row-level security is enabled for a table, but no applicable policies
- exist, a <span class="quote">“<span class="quote">default deny</span>”</span> policy is assumed, so that no rows will
- be visible or updatable.
- </p></div><div class="refsect1" id="id-1.9.3.75.6"><h2>Parameters</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term"><em class="replaceable"><code>name</code></em></span></dt><dd><p>
- The name of the policy to be created. This must be distinct from the
- name of any other policy for the table.
- </p></dd><dt><span class="term"><em class="replaceable"><code>table_name</code></em></span></dt><dd><p>
- The name (optionally schema-qualified) of the table the
- policy applies to.
- </p></dd><dt><span class="term"><code class="literal">PERMISSIVE</code></span></dt><dd><p>
- Specify that the policy is to be created as a permissive policy.
- All permissive policies which are applicable to a given query will
- be combined together using the Boolean <span class="quote">“<span class="quote">OR</span>”</span> operator. By creating
- permissive policies, administrators can add to the set of records
- which can be accessed. Policies are permissive by default.
- </p></dd><dt><span class="term"><code class="literal">RESTRICTIVE</code></span></dt><dd><p>
- Specify that the policy is to be created as a restrictive policy.
- All restrictive policies which are applicable to a given query will
- be combined together using the Boolean <span class="quote">“<span class="quote">AND</span>”</span> operator. By creating
- restrictive policies, administrators can reduce the set of records
- which can be accessed as all restrictive policies must be passed for
- each record.
- </p><p>
- Note that there needs to be at least one permissive policy to grant
- access to records before restrictive policies can be usefully used to
- reduce that access. If only restrictive policies exist, then no records
- will be accessible. When a mix of permissive and restrictive policies
- are present, a record is only accessible if at least one of the
- permissive policies passes, in addition to all the restrictive
- policies.
- </p></dd><dt><span class="term"><em class="replaceable"><code>command</code></em></span></dt><dd><p>
- The command to which the policy applies. Valid options are
- <code class="command">ALL</code>, <code class="command">SELECT</code>,
- <code class="command">INSERT</code>, <code class="command">UPDATE</code>,
- and <code class="command">DELETE</code>.
- <code class="command">ALL</code> is the default.
- See below for specifics regarding how these are applied.
- </p></dd><dt><span class="term"><em class="replaceable"><code>role_name</code></em></span></dt><dd><p>
- The role(s) to which the policy is to be applied. The default is
- <code class="literal">PUBLIC</code>, which will apply the policy to all roles.
- </p></dd><dt><span class="term"><em class="replaceable"><code>using_expression</code></em></span></dt><dd><p>
- Any <acronym class="acronym">SQL</acronym> conditional expression (returning
- <code class="type">boolean</code>). The conditional expression cannot contain
- any aggregate or window functions. This expression will be added
- to queries that refer to the table if row level security is enabled.
- Rows for which the expression returns true will be visible. Any
- rows for which the expression returns false or null will not be
- visible to the user (in a <code class="command">SELECT</code>), and will not be
- available for modification (in an <code class="command">UPDATE</code>
- or <code class="command">DELETE</code>). Such rows are silently suppressed; no error
- is reported.
- </p></dd><dt><span class="term"><em class="replaceable"><code>check_expression</code></em></span></dt><dd><p>
- Any <acronym class="acronym">SQL</acronym> conditional expression (returning
- <code class="type">boolean</code>). The conditional expression cannot contain
- any aggregate or window functions. This expression will be used in
- <code class="command">INSERT</code> and <code class="command">UPDATE</code> queries against
- the table if row level security is enabled. Only rows for which the
- expression evaluates to true will be allowed. An error will be thrown
- if the expression evaluates to false or null for any of the records
- inserted or any of the records that result from the update. Note that
- the <em class="replaceable"><code>check_expression</code></em> is
- evaluated against the proposed new contents of the row, not the
- original contents.
- </p></dd></dl></div><div class="refsect2" id="id-1.9.3.75.6.3"><h3>Per-Command Policies</h3><div class="variablelist"><dl class="variablelist"><dt id="SQL-CREATEPOLICY-ALL"><span class="term"><code class="literal">ALL</code></span></dt><dd><p>
- Using <code class="literal">ALL</code> for a policy means that it will apply
- to all commands, regardless of the type of command. If an
- <code class="literal">ALL</code> policy exists and more specific policies
- exist, then both the <code class="literal">ALL</code> policy and the more
- specific policy (or policies) will be applied.
- Additionally, <code class="literal">ALL</code> policies will be applied to
- both the selection side of a query and the modification side, using
- the <code class="literal">USING</code> expression for both cases if only
- a <code class="literal">USING</code> expression has been defined.
- </p><p>
- As an example, if an <code class="literal">UPDATE</code> is issued, then the
- <code class="literal">ALL</code> policy will be applicable both to what the
- <code class="literal">UPDATE</code> will be able to select as rows to be
- updated (applying the <code class="literal">USING</code> expression),
- and to the resulting updated rows, to check if they are permitted
- to be added to the table (applying the <code class="literal">WITH CHECK</code>
- expression, if defined, and the <code class="literal">USING</code> expression
- otherwise). If an <code class="command">INSERT</code>
- or <code class="command">UPDATE</code> command attempts to add rows to the
- table that do not pass the <code class="literal">ALL</code>
- policy's <code class="literal">WITH CHECK</code> expression, the entire
- command will be aborted.
- </p></dd><dt id="SQL-CREATEPOLICY-SELECT"><span class="term"><code class="literal">SELECT</code></span></dt><dd><p>
- Using <code class="literal">SELECT</code> for a policy means that it will apply
- to <code class="literal">SELECT</code> queries and whenever
- <code class="literal">SELECT</code> permissions are required on the relation the
- policy is defined for. The result is that only those records from the
- relation that pass the <code class="literal">SELECT</code> policy will be
- returned during a <code class="literal">SELECT</code> query, and that queries
- that require <code class="literal">SELECT</code> permissions, such as
- <code class="literal">UPDATE</code>, will also only see those records
- that are allowed by the <code class="literal">SELECT</code> policy.
- A <code class="literal">SELECT</code> policy cannot have a <code class="literal">WITH
- CHECK</code> expression, as it only applies in cases where
- records are being retrieved from the relation.
- </p></dd><dt id="SQL-CREATEPOLICY-INSERT"><span class="term"><code class="literal">INSERT</code></span></dt><dd><p>
- Using <code class="literal">INSERT</code> for a policy means that it will apply
- to <code class="literal">INSERT</code> commands. Rows being inserted that do
- not pass this policy will result in a policy violation error, and the
- entire <code class="literal">INSERT</code> command will be aborted.
- An <code class="literal">INSERT</code> policy cannot have
- a <code class="literal">USING</code> expression, as it only applies in cases
- where records are being added to the relation.
- </p><p>
- Note that <code class="literal">INSERT</code> with <code class="literal">ON CONFLICT DO
- UPDATE</code> checks <code class="literal">INSERT</code> policies'
- <code class="literal">WITH CHECK</code> expressions only for rows appended
- to the relation by the <code class="literal">INSERT</code> path.
- </p></dd><dt id="SQL-CREATEPOLICY-UPDATE"><span class="term"><code class="literal">UPDATE</code></span></dt><dd><p>
- Using <code class="literal">UPDATE</code> for a policy means that it will apply
- to <code class="literal">UPDATE</code>, <code class="literal">SELECT FOR UPDATE</code>
- and <code class="literal">SELECT FOR SHARE</code> commands, as well as
- auxiliary <code class="literal">ON CONFLICT DO UPDATE</code> clauses of
- <code class="literal">INSERT</code> commands. Since <code class="literal">UPDATE</code>
- involves pulling an existing record and replacing it with a new
- modified record, <code class="literal">UPDATE</code>
- policies accept both a <code class="literal">USING</code> expression and
- a <code class="literal">WITH CHECK</code> expression.
- The <code class="literal">USING</code> expression determines which records
- the <code class="literal">UPDATE</code> command will see to operate against,
- while the <code class="literal">WITH CHECK</code> expression defines which
- modified rows are allowed to be stored back into the relation.
- </p><p>
- Any rows whose updated values do not pass the
- <code class="literal">WITH CHECK</code> expression will cause an error, and the
- entire command will be aborted. If only a <code class="literal">USING</code>
- clause is specified, then that clause will be used for both
- <code class="literal">USING</code> and <code class="literal">WITH CHECK</code> cases.
- </p><p>
- Typically an <code class="literal">UPDATE</code> command also needs to read
- data from columns in the relation being updated (e.g., in a
- <code class="literal">WHERE</code> clause or a <code class="literal">RETURNING</code>
- clause, or in an expression on the right hand side of the
- <code class="literal">SET</code> clause). In this case,
- <code class="literal">SELECT</code> rights are also required on the relation
- being updated, and the appropriate <code class="literal">SELECT</code> or
- <code class="literal">ALL</code> policies will be applied in addition to
- the <code class="literal">UPDATE</code> policies. Thus the user must have
- access to the row(s) being updated through a <code class="literal">SELECT</code>
- or <code class="literal">ALL</code> policy in addition to being granted
- permission to update the row(s) via an <code class="literal">UPDATE</code>
- or <code class="literal">ALL</code> policy.
- </p><p>
- When an <code class="literal">INSERT</code> command has an auxiliary
- <code class="literal">ON CONFLICT DO UPDATE</code> clause, if the
- <code class="literal">UPDATE</code> path is taken, the row to be updated is
- first checked against the <code class="literal">USING</code> expressions of
- any <code class="literal">UPDATE</code> policies, and then the new updated row
- is checked against the <code class="literal">WITH CHECK</code> expressions.
- Note, however, that unlike a standalone <code class="literal">UPDATE</code>
- command, if the existing row does not pass the
- <code class="literal">USING</code> expressions, an error will be thrown (the
- <code class="literal">UPDATE</code> path will <span class="emphasis"><em>never</em></span> be silently
- avoided).
- </p></dd><dt id="SQL-CREATEPOLICY-DELETE"><span class="term"><code class="literal">DELETE</code></span></dt><dd><p>
- Using <code class="literal">DELETE</code> for a policy means that it will apply
- to <code class="literal">DELETE</code> commands. Only rows that pass this
- policy will be seen by a <code class="literal">DELETE</code> command. There can
- be rows that are visible through a <code class="literal">SELECT</code> that are
- not available for deletion, if they do not pass the
- <code class="literal">USING</code> expression for
- the <code class="literal">DELETE</code> policy.
- </p><p>
- In most cases a <code class="literal">DELETE</code> command also needs to read
- data from columns in the relation that it is deleting from (e.g.,
- in a <code class="literal">WHERE</code> clause or a
- <code class="literal">RETURNING</code> clause). In this case,
- <code class="literal">SELECT</code> rights are also required on the relation,
- and the appropriate <code class="literal">SELECT</code> or
- <code class="literal">ALL</code> policies will be applied in addition to
- the <code class="literal">DELETE</code> policies. Thus the user must have
- access to the row(s) being deleted through a <code class="literal">SELECT</code>
- or <code class="literal">ALL</code> policy in addition to being granted
- permission to delete the row(s) via a <code class="literal">DELETE</code> or
- <code class="literal">ALL</code> policy.
- </p><p>
- A <code class="literal">DELETE</code> policy cannot have a <code class="literal">WITH
- CHECK</code> expression, as it only applies in cases where
- records are being deleted from the relation, so that there is no
- new row to check.
- </p></dd></dl></div><div class="table" id="SQL-CREATEPOLICY-SUMMARY"><p class="title"><strong>Table 256. Policies Applied by Command Type</strong></p><div class="table-contents"><table class="table" summary="Policies Applied by Command Type" border="1"><colgroup><col /><col /><col /><col class="update-using" /><col class="update-check" /><col /></colgroup><thead><tr><th rowspan="2">Command</th><th><code class="literal">SELECT/ALL policy</code></th><th><code class="literal">INSERT/ALL policy</code></th><th colspan="2"><code class="literal">UPDATE/ALL policy</code></th><th><code class="literal">DELETE/ALL policy</code></th></tr><tr><th><code class="literal">USING expression</code></th><th><code class="literal">WITH CHECK expression</code></th><th><code class="literal">USING expression</code></th><th><code class="literal">WITH CHECK expression</code></th><th><code class="literal">USING expression</code></th></tr></thead><tbody><tr><td><code class="command">SELECT</code></td><td>Existing row</td><td>—</td><td>—</td><td>—</td><td>—</td></tr><tr><td><code class="command">SELECT FOR UPDATE/SHARE</code></td><td>Existing row</td><td>—</td><td>Existing row</td><td>—</td><td>—</td></tr><tr><td><code class="command">INSERT</code></td><td>—</td><td>New row</td><td>—</td><td>—</td><td>—</td></tr><tr><td><code class="command">INSERT ... RETURNING</code></td><td>
- New row <a href="#ftn.RLS-SELECT-PRIV" class="footnote"><sup class="footnote" id="RLS-SELECT-PRIV">[a]</sup></a>
- </td><td>New row</td><td>—</td><td>—</td><td>—</td></tr><tr><td><code class="command">UPDATE</code></td><td>
- Existing & new rows <a href="sql-createpolicy.html#ftn.RLS-SELECT-PRIV" class="footnoteref"><sup class="footnoteref">[a]</sup></a>
- </td><td>—</td><td>Existing row</td><td>New row</td><td>—</td></tr><tr><td><code class="command">DELETE</code></td><td>
- Existing row <a href="sql-createpolicy.html#ftn.RLS-SELECT-PRIV" class="footnoteref"><sup class="footnoteref">[a]</sup></a>
- </td><td>—</td><td>—</td><td>—</td><td>Existing row</td></tr><tr><td><code class="command">ON CONFLICT DO UPDATE</code></td><td>Existing & new rows</td><td>—</td><td>Existing row</td><td>New row</td><td>—</td></tr></tbody><tbody class="footnotes"><tr><td colspan="6"><div id="ftn.RLS-SELECT-PRIV" class="footnote"><p><a href="#RLS-SELECT-PRIV" class="para"><sup class="para">[a] </sup></a>
- If read access is required to the existing or new row (for example,
- a <code class="literal">WHERE</code> or <code class="literal">RETURNING</code> clause
- that refers to columns from the relation).
- </p></div></td></tr></tbody></table></div></div><br class="table-break" /></div><div class="refsect2" id="id-1.9.3.75.6.4"><h3>Application of Multiple Policies</h3><p>
- When multiple policies of different command types apply to the same command
- (for example, <code class="literal">SELECT</code> and <code class="literal">UPDATE</code>
- policies applied to an <code class="literal">UPDATE</code> command), then the user
- must have both types of permissions (for example, permission to select rows
- from the relation as well as permission to update them). Thus the
- expressions for one type of policy are combined with the expressions for
- the other type of policy using the <code class="literal">AND</code> operator.
- </p><p>
- When multiple policies of the same command type apply to the same command,
- then there must be at least one <code class="literal">PERMISSIVE</code> policy
- granting access to the relation, and all of the
- <code class="literal">RESTRICTIVE</code> policies must pass. Thus all the
- <code class="literal">PERMISSIVE</code> policy expressions are combined using
- <code class="literal">OR</code>, all the <code class="literal">RESTRICTIVE</code> policy
- expressions are combined using <code class="literal">AND</code>, and the results are
- combined using <code class="literal">AND</code>. If there are no
- <code class="literal">PERMISSIVE</code> policies, then access is denied.
- </p><p>
- Note that, for the purposes of combining multiple policies,
- <code class="literal">ALL</code> policies are treated as having the same type as
- whichever other type of policy is being applied.
- </p><p>
- For example, in an <code class="literal">UPDATE</code> command requiring both
- <code class="literal">SELECT</code> and <code class="literal">UPDATE</code> permissions, if
- there are multiple applicable policies of each type, they will be combined
- as follows:
-
- </p><pre class="programlisting">
- <em class="replaceable"><code>expression</code></em> from RESTRICTIVE SELECT/ALL policy 1
- AND
- <em class="replaceable"><code>expression</code></em> from RESTRICTIVE SELECT/ALL policy 2
- AND
- ...
- AND
- (
- <em class="replaceable"><code>expression</code></em> from PERMISSIVE SELECT/ALL policy 1
- OR
- <em class="replaceable"><code>expression</code></em> from PERMISSIVE SELECT/ALL policy 2
- OR
- ...
- )
- AND
- <em class="replaceable"><code>expression</code></em> from RESTRICTIVE UPDATE/ALL policy 1
- AND
- <em class="replaceable"><code>expression</code></em> from RESTRICTIVE UPDATE/ALL policy 2
- AND
- ...
- AND
- (
- <em class="replaceable"><code>expression</code></em> from PERMISSIVE UPDATE/ALL policy 1
- OR
- <em class="replaceable"><code>expression</code></em> from PERMISSIVE UPDATE/ALL policy 2
- OR
- ...
- )
- </pre></div></div><div class="refsect1" id="id-1.9.3.75.7"><h2>Notes</h2><p>
- You must be the owner of a table to create or change policies for it.
- </p><p>
- While policies will be applied for explicit queries against tables
- in the database, they are not applied when the system is performing internal
- referential integrity checks or validating constraints. This means there are
- indirect ways to determine that a given value exists. An example of this is
- attempting to insert a duplicate value into a column that is a primary key
- or has a unique constraint. If the insert fails then the user can infer that
- the value already exists. (This example assumes that the user is permitted by
- policy to insert records which they are not allowed to see.) Another example
- is where a user is allowed to insert into a table which references another,
- otherwise hidden table. Existence can be determined by the user inserting
- values into the referencing table, where success would indicate that the
- value exists in the referenced table. These issues can be addressed by
- carefully crafting policies to prevent users from being able to insert,
- delete, or update records at all which might possibly indicate a value they
- are not otherwise able to see, or by using generated values (e.g., surrogate
- keys) instead of keys with external meanings.
- </p><p>
- Generally, the system will enforce filter conditions imposed using
- security policies prior to qualifications that appear in user queries,
- in order to prevent inadvertent exposure of the protected data to
- user-defined functions which might not be trustworthy. However,
- functions and operators marked by the system (or the system
- administrator) as <code class="literal">LEAKPROOF</code> may be evaluated before
- policy expressions, as they are assumed to be trustworthy.
- </p><p>
- Since policy expressions
- are added to the user's query directly, they will be run with the rights of
- the user running the overall query. Therefore, users who are using a given
- policy must be able to access any tables or functions referenced in the
- expression or they will simply receive a permission denied error when
- attempting to query the table that has row-level security enabled.
- This does not change how views
- work, however. As with normal queries and views, permission checks and
- policies for the tables which are referenced by a view will use the view
- owner's rights and any policies which apply to the view owner.
- </p><p>
- Additional discussion and practical examples can be found
- in <a class="xref" href="ddl-rowsecurity.html" title="5.8. Row Security Policies">Section 5.8</a>.
- </p></div><div class="refsect1" id="id-1.9.3.75.8"><h2>Compatibility</h2><p>
- <code class="command">CREATE POLICY</code> is a <span class="productname">PostgreSQL</span>
- extension.
- </p></div><div class="refsect1" id="id-1.9.3.75.9"><h2>See Also</h2><span class="simplelist"><a class="xref" href="sql-alterpolicy.html" title="ALTER POLICY"><span class="refentrytitle">ALTER POLICY</span></a>, <a class="xref" href="sql-droppolicy.html" title="DROP POLICY"><span class="refentrytitle">DROP POLICY</span></a>, <a class="xref" href="sql-altertable.html" title="ALTER TABLE"><span class="refentrytitle">ALTER TABLE</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-createopfamily.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="sql-commands.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="sql-createprocedure.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">CREATE OPERATOR FAMILY </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> CREATE PROCEDURE</td></tr></table></div></body></html>
|