Current File : //usr/share/doc/postgresql-9.2.24/html/plpgsql-statements.html |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML
><HEAD
><TITLE
>Basic Statements</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
REV="MADE"
HREF="mailto:pgsql-docs@postgresql.org"><LINK
REL="HOME"
TITLE="PostgreSQL 9.2.24 Documentation"
HREF="index.html"><LINK
REL="UP"
TITLE="PL/pgSQL - SQL Procedural Language"
HREF="plpgsql.html"><LINK
REL="PREVIOUS"
TITLE="Expressions"
HREF="plpgsql-expressions.html"><LINK
REL="NEXT"
TITLE="Control Structures"
HREF="plpgsql-control-structures.html"><LINK
REL="STYLESHEET"
TYPE="text/css"
HREF="stylesheet.css"><META
HTTP-EQUIV="Content-Type"
CONTENT="text/html; charset=ISO-8859-1"><META
NAME="creation"
CONTENT="2017-11-06T22:43:11"></HEAD
><BODY
CLASS="SECT1"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="5"
ALIGN="center"
VALIGN="bottom"
><A
HREF="index.html"
>PostgreSQL 9.2.24 Documentation</A
></TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="top"
><A
TITLE="Expressions"
HREF="plpgsql-expressions.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="top"
><A
HREF="plpgsql.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="60%"
ALIGN="center"
VALIGN="bottom"
>Chapter 39. <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> - <ACRONYM
CLASS="ACRONYM"
>SQL</ACRONYM
> Procedural Language</TD
><TD
WIDTH="20%"
ALIGN="right"
VALIGN="top"
><A
TITLE="Control Structures"
HREF="plpgsql-control-structures.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="PLPGSQL-STATEMENTS"
>39.5. Basic Statements</A
></H1
><P
> In this section and the following ones, we describe all the statement
types that are explicitly understood by
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
>.
Anything not recognized as one of these statement types is presumed
to be an SQL command and is sent to the main database engine to execute,
as described in <A
HREF="plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-NORESULT"
>Section 39.5.2</A
>
and <A
HREF="plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW"
>Section 39.5.3</A
>.
</P
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="PLPGSQL-STATEMENTS-ASSIGNMENT"
>39.5.1. Assignment</A
></H2
><P
> An assignment of a value to a <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
>
variable is written as:
</P><PRE
CLASS="SYNOPSIS"
><TT
CLASS="REPLACEABLE"
><I
>variable</I
></TT
> := <TT
CLASS="REPLACEABLE"
><I
>expression</I
></TT
>;</PRE
><P>
As explained previously, the expression in such a statement is evaluated
by means of an SQL <TT
CLASS="COMMAND"
>SELECT</TT
> command sent to the main
database engine. The expression must yield a single value (possibly
a row value, if the variable is a row or record variable). The target
variable can be a simple variable (optionally qualified with a block
name), a field of a row or record variable, or an element of an array
that is a simple variable or field.
</P
><P
> If the expression's result data type doesn't match the variable's
data type, or the variable has a specific size/precision
(like <TT
CLASS="TYPE"
>char(20)</TT
>), the result value will be implicitly
converted by the <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> interpreter using
the result type's output-function and
the variable type's input-function. Note that this could potentially
result in run-time errors generated by the input function, if the
string form of the result value is not acceptable to the input function.
</P
><P
> Examples:
</P><PRE
CLASS="PROGRAMLISTING"
>tax := subtotal * 0.06;
my_record.user_id := 20;</PRE
><P>
</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="PLPGSQL-STATEMENTS-SQL-NORESULT"
>39.5.2. Executing a Command With No Result</A
></H2
><P
> For any SQL command that does not return rows, for example
<TT
CLASS="COMMAND"
>INSERT</TT
> without a <TT
CLASS="LITERAL"
>RETURNING</TT
> clause, you can
execute the command within a <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> function
just by writing the command.
</P
><P
> Any <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> variable name appearing
in the command text is treated as a parameter, and then the
current value of the variable is provided as the parameter value
at run time. This is exactly like the processing described earlier
for expressions; for details see <A
HREF="plpgsql-implementation.html#PLPGSQL-VAR-SUBST"
>Section 39.10.1</A
>.
</P
><P
> When executing a SQL command in this way,
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> may cache and re-use the execution
plan for the command, as discussed in
<A
HREF="plpgsql-implementation.html#PLPGSQL-PLAN-CACHING"
>Section 39.10.2</A
>.
</P
><P
> Sometimes it is useful to evaluate an expression or <TT
CLASS="COMMAND"
>SELECT</TT
>
query but discard the result, for example when calling a function
that has side-effects but no useful result value. To do
this in <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
>, use the
<TT
CLASS="COMMAND"
>PERFORM</TT
> statement:
</P><PRE
CLASS="SYNOPSIS"
>PERFORM <TT
CLASS="REPLACEABLE"
><I
>query</I
></TT
>;</PRE
><P>
This executes <TT
CLASS="REPLACEABLE"
><I
>query</I
></TT
> and discards the
result. Write the <TT
CLASS="REPLACEABLE"
><I
>query</I
></TT
> the same
way you would write an SQL <TT
CLASS="COMMAND"
>SELECT</TT
> command, but replace the
initial keyword <TT
CLASS="COMMAND"
>SELECT</TT
> with <TT
CLASS="COMMAND"
>PERFORM</TT
>.
For <TT
CLASS="COMMAND"
>WITH</TT
> queries, use <TT
CLASS="COMMAND"
>PERFORM</TT
> and then
place the query in parentheses. (In this case, the query can only
return one row.)
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> variables will be
substituted into the query just as for commands that return no result,
and the plan is cached in the same way. Also, the special variable
<TT
CLASS="LITERAL"
>FOUND</TT
> is set to true if the query produced at
least one row, or false if it produced no rows (see
<A
HREF="plpgsql-statements.html#PLPGSQL-STATEMENTS-DIAGNOSTICS"
>Section 39.5.5</A
>).
</P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
> One might expect that writing <TT
CLASS="COMMAND"
>SELECT</TT
> directly
would accomplish this result, but at
present the only accepted way to do it is
<TT
CLASS="COMMAND"
>PERFORM</TT
>. A SQL command that can return rows,
such as <TT
CLASS="COMMAND"
>SELECT</TT
>, will be rejected as an error
unless it has an <TT
CLASS="LITERAL"
>INTO</TT
> clause as discussed in the
next section.
</P
></BLOCKQUOTE
></DIV
><P
> An example:
</P><PRE
CLASS="PROGRAMLISTING"
>PERFORM create_mv('cs_session_page_requests_mv', my_query);</PRE
><P>
</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="PLPGSQL-STATEMENTS-SQL-ONEROW"
>39.5.3. Executing a Query with a Single-row Result</A
></H2
><P
> The result of a SQL command yielding a single row (possibly of multiple
columns) can be assigned to a record variable, row-type variable, or list
of scalar variables. This is done by writing the base SQL command and
adding an <TT
CLASS="LITERAL"
>INTO</TT
> clause. For example,
</P><PRE
CLASS="SYNOPSIS"
>SELECT <TT
CLASS="REPLACEABLE"
><I
>select_expressions</I
></TT
> INTO [<SPAN
CLASS="OPTIONAL"
>STRICT</SPAN
>] <TT
CLASS="REPLACEABLE"
><I
>target</I
></TT
> FROM ...;
INSERT ... RETURNING <TT
CLASS="REPLACEABLE"
><I
>expressions</I
></TT
> INTO [<SPAN
CLASS="OPTIONAL"
>STRICT</SPAN
>] <TT
CLASS="REPLACEABLE"
><I
>target</I
></TT
>;
UPDATE ... RETURNING <TT
CLASS="REPLACEABLE"
><I
>expressions</I
></TT
> INTO [<SPAN
CLASS="OPTIONAL"
>STRICT</SPAN
>] <TT
CLASS="REPLACEABLE"
><I
>target</I
></TT
>;
DELETE ... RETURNING <TT
CLASS="REPLACEABLE"
><I
>expressions</I
></TT
> INTO [<SPAN
CLASS="OPTIONAL"
>STRICT</SPAN
>] <TT
CLASS="REPLACEABLE"
><I
>target</I
></TT
>;</PRE
><P>
where <TT
CLASS="REPLACEABLE"
><I
>target</I
></TT
> can be a record variable, a row
variable, or a comma-separated list of simple variables and
record/row fields.
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> variables will be
substituted into the rest of the query, and the plan is cached,
just as described above for commands that do not return rows.
This works for <TT
CLASS="COMMAND"
>SELECT</TT
>,
<TT
CLASS="COMMAND"
>INSERT</TT
>/<TT
CLASS="COMMAND"
>UPDATE</TT
>/<TT
CLASS="COMMAND"
>DELETE</TT
> with
<TT
CLASS="LITERAL"
>RETURNING</TT
>, and utility commands that return row-set
results (such as <TT
CLASS="COMMAND"
>EXPLAIN</TT
>).
Except for the <TT
CLASS="LITERAL"
>INTO</TT
> clause, the SQL command is the same
as it would be written outside <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
>.
</P
><DIV
CLASS="TIP"
><BLOCKQUOTE
CLASS="TIP"
><P
><B
>Tip: </B
> Note that this interpretation of <TT
CLASS="COMMAND"
>SELECT</TT
> with <TT
CLASS="LITERAL"
>INTO</TT
>
is quite different from <SPAN
CLASS="PRODUCTNAME"
>PostgreSQL</SPAN
>'s regular
<TT
CLASS="COMMAND"
>SELECT INTO</TT
> command, wherein the <TT
CLASS="LITERAL"
>INTO</TT
>
target is a newly created table. If you want to create a table from a
<TT
CLASS="COMMAND"
>SELECT</TT
> result inside a
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> function, use the syntax
<TT
CLASS="COMMAND"
>CREATE TABLE ... AS SELECT</TT
>.
</P
></BLOCKQUOTE
></DIV
><P
> If a row or a variable list is used as target, the query's result columns
must exactly match the structure of the target as to number and data
types, or else a run-time error
occurs. When a record variable is the target, it automatically
configures itself to the row type of the query result columns.
</P
><P
> The <TT
CLASS="LITERAL"
>INTO</TT
> clause can appear almost anywhere in the SQL
command. Customarily it is written either just before or just after
the list of <TT
CLASS="REPLACEABLE"
><I
>select_expressions</I
></TT
> in a
<TT
CLASS="COMMAND"
>SELECT</TT
> command, or at the end of the command for other
command types. It is recommended that you follow this convention
in case the <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> parser becomes
stricter in future versions.
</P
><P
> If <TT
CLASS="LITERAL"
>STRICT</TT
> is not specified in the <TT
CLASS="LITERAL"
>INTO</TT
>
clause, then <TT
CLASS="REPLACEABLE"
><I
>target</I
></TT
> will be set to the first
row returned by the query, or to nulls if the query returned no rows.
(Note that <SPAN
CLASS="QUOTE"
>"the first row"</SPAN
> is not
well-defined unless you've used <TT
CLASS="LITERAL"
>ORDER BY</TT
>.) Any result rows
after the first row are discarded.
You can check the special <TT
CLASS="LITERAL"
>FOUND</TT
> variable (see
<A
HREF="plpgsql-statements.html#PLPGSQL-STATEMENTS-DIAGNOSTICS"
>Section 39.5.5</A
>) to
determine whether a row was returned:
</P><PRE
CLASS="PROGRAMLISTING"
>SELECT * INTO myrec FROM emp WHERE empname = myname;
IF NOT FOUND THEN
RAISE EXCEPTION 'employee % not found', myname;
END IF;</PRE
><P>
If the <TT
CLASS="LITERAL"
>STRICT</TT
> option is specified, the query must
return exactly one row or a run-time error will be reported, either
<TT
CLASS="LITERAL"
>NO_DATA_FOUND</TT
> (no rows) or <TT
CLASS="LITERAL"
>TOO_MANY_ROWS</TT
>
(more than one row). You can use an exception block if you wish
to catch the error, for example:
</P><PRE
CLASS="PROGRAMLISTING"
>BEGIN
SELECT * INTO STRICT myrec FROM emp WHERE empname = myname;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE EXCEPTION 'employee % not found', myname;
WHEN TOO_MANY_ROWS THEN
RAISE EXCEPTION 'employee % not unique', myname;
END;</PRE
><P>
Successful execution of a command with <TT
CLASS="LITERAL"
>STRICT</TT
>
always sets <TT
CLASS="LITERAL"
>FOUND</TT
> to true.
</P
><P
> For <TT
CLASS="COMMAND"
>INSERT</TT
>/<TT
CLASS="COMMAND"
>UPDATE</TT
>/<TT
CLASS="COMMAND"
>DELETE</TT
> with
<TT
CLASS="LITERAL"
>RETURNING</TT
>, <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> reports
an error for more than one returned row, even when
<TT
CLASS="LITERAL"
>STRICT</TT
> is not specified. This is because there
is no option such as <TT
CLASS="LITERAL"
>ORDER BY</TT
> with which to determine
which affected row should be returned.
</P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
> The <TT
CLASS="LITERAL"
>STRICT</TT
> option matches the behavior of
Oracle PL/SQL's <TT
CLASS="COMMAND"
>SELECT INTO</TT
> and related statements.
</P
></BLOCKQUOTE
></DIV
><P
> To handle cases where you need to process multiple result rows
from a SQL query, see <A
HREF="plpgsql-control-structures.html#PLPGSQL-RECORDS-ITERATING"
>Section 39.6.4</A
>.
</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="PLPGSQL-STATEMENTS-EXECUTING-DYN"
>39.5.4. Executing Dynamic Commands</A
></H2
><P
> Oftentimes you will want to generate dynamic commands inside your
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> functions, that is, commands
that will involve different tables or different data types each
time they are executed. <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
>'s
normal attempts to cache plans for commands (as discussed in
<A
HREF="plpgsql-implementation.html#PLPGSQL-PLAN-CACHING"
>Section 39.10.2</A
>) will not work in such
scenarios. To handle this sort of problem, the
<TT
CLASS="COMMAND"
>EXECUTE</TT
> statement is provided:
</P><PRE
CLASS="SYNOPSIS"
>EXECUTE <TT
CLASS="REPLACEABLE"
><I
>command-string</I
></TT
> [<SPAN
CLASS="OPTIONAL"
> INTO [<SPAN
CLASS="OPTIONAL"
>STRICT</SPAN
>] <TT
CLASS="REPLACEABLE"
><I
>target</I
></TT
> </SPAN
>] [<SPAN
CLASS="OPTIONAL"
> USING <TT
CLASS="REPLACEABLE"
><I
>expression</I
></TT
> [<SPAN
CLASS="OPTIONAL"
>, ... </SPAN
>] </SPAN
>];</PRE
><P>
where <TT
CLASS="REPLACEABLE"
><I
>command-string</I
></TT
> is an expression
yielding a string (of type <TT
CLASS="TYPE"
>text</TT
>) containing the
command to be executed. The optional <TT
CLASS="REPLACEABLE"
><I
>target</I
></TT
>
is a record variable, a row variable, or a comma-separated list of
simple variables and record/row fields, into which the results of
the command will be stored. The optional <TT
CLASS="LITERAL"
>USING</TT
> expressions
supply values to be inserted into the command.
</P
><P
> No substitution of <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> variables is done on the
computed command string. Any required variable values must be inserted
in the command string as it is constructed; or you can use parameters
as described below.
</P
><P
> Also, there is no plan caching for commands executed via
<TT
CLASS="COMMAND"
>EXECUTE</TT
>. Instead, the command is always planned
each time the statement is run. Thus the command
string can be dynamically created within the function to perform
actions on different tables and columns.
</P
><P
> The <TT
CLASS="LITERAL"
>INTO</TT
> clause specifies where the results of
a SQL command returning rows should be assigned. If a row
or variable list is provided, it must exactly match the structure
of the query's results (when a
record variable is used, it will configure itself to match the
result structure automatically). If multiple rows are returned,
only the first will be assigned to the <TT
CLASS="LITERAL"
>INTO</TT
>
variable. If no rows are returned, NULL is assigned to the
<TT
CLASS="LITERAL"
>INTO</TT
> variable(s). If no <TT
CLASS="LITERAL"
>INTO</TT
>
clause is specified, the query results are discarded.
</P
><P
> If the <TT
CLASS="LITERAL"
>STRICT</TT
> option is given, an error is reported
unless the query produces exactly one row.
</P
><P
> The command string can use parameter values, which are referenced
in the command as <TT
CLASS="LITERAL"
>$1</TT
>, <TT
CLASS="LITERAL"
>$2</TT
>, etc.
These symbols refer to values supplied in the <TT
CLASS="LITERAL"
>USING</TT
>
clause. This method is often preferable to inserting data values
into the command string as text: it avoids run-time overhead of
converting the values to text and back, and it is much less prone
to SQL-injection attacks since there is no need for quoting or escaping.
An example is:
</P><PRE
CLASS="PROGRAMLISTING"
>EXECUTE 'SELECT count(*) FROM mytable WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;</PRE
><P>
</P
><P
> Note that parameter symbols can only be used for data values
— if you want to use dynamically determined table or column
names, you must insert them into the command string textually.
For example, if the preceding query needed to be done against a
dynamically selected table, you could do this:
</P><PRE
CLASS="PROGRAMLISTING"
>EXECUTE 'SELECT count(*) FROM '
|| tabname::regclass
|| ' WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;</PRE
><P>
Another restriction on parameter symbols is that they only work in
<TT
CLASS="COMMAND"
>SELECT</TT
>, <TT
CLASS="COMMAND"
>INSERT</TT
>, <TT
CLASS="COMMAND"
>UPDATE</TT
>, and
<TT
CLASS="COMMAND"
>DELETE</TT
> commands. In other statement
types (generically called utility statements), you must insert
values textually even if they are just data values.
</P
><P
> An <TT
CLASS="COMMAND"
>EXECUTE</TT
> with a simple constant command string and some
<TT
CLASS="LITERAL"
>USING</TT
> parameters, as in the first example above, is
functionally equivalent to just writing the command directly in
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> and allowing replacement of
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> variables to happen automatically.
The important difference is that <TT
CLASS="COMMAND"
>EXECUTE</TT
> will re-plan
the command on each execution, generating a plan that is specific
to the current parameter values; whereas
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> may otherwise create a generic plan
and cache it for re-use. In situations where the best plan depends
strongly on the parameter values, it can be helpful to use
<TT
CLASS="COMMAND"
>EXECUTE</TT
> to positively ensure that a generic plan is not
selected.
</P
><P
> <TT
CLASS="COMMAND"
>SELECT INTO</TT
> is not currently supported within
<TT
CLASS="COMMAND"
>EXECUTE</TT
>; instead, execute a plain <TT
CLASS="COMMAND"
>SELECT</TT
>
command and specify <TT
CLASS="LITERAL"
>INTO</TT
> as part of the <TT
CLASS="COMMAND"
>EXECUTE</TT
>
itself.
</P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
> The <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
>
<TT
CLASS="COMMAND"
>EXECUTE</TT
> statement is not related to the
<A
HREF="sql-execute.html"
>EXECUTE</A
> SQL
statement supported by the
<SPAN
CLASS="PRODUCTNAME"
>PostgreSQL</SPAN
> server. The server's
<TT
CLASS="COMMAND"
>EXECUTE</TT
> statement cannot be used directly within
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> functions (and is not needed).
</P
></BLOCKQUOTE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="PLPGSQL-QUOTE-LITERAL-EXAMPLE"
></A
><P
><B
>Example 39-1. Quoting Values In Dynamic Queries</B
></P
><P
> When working with dynamic commands you will often have to handle escaping
of single quotes. The recommended method for quoting fixed text in your
function body is dollar quoting. (If you have legacy code that does
not use dollar quoting, please refer to the
overview in <A
HREF="plpgsql-development-tips.html#PLPGSQL-QUOTE-TIPS"
>Section 39.11.1</A
>, which can save you
some effort when translating said code to a more reasonable scheme.)
</P
><P
> Dynamic values that are to be inserted into the constructed
query require careful handling since they might themselves contain
quote characters.
An example (this assumes that you are using dollar quoting for the
function as a whole, so the quote marks need not be doubled):
</P><PRE
CLASS="PROGRAMLISTING"
>EXECUTE 'UPDATE tbl SET '
|| quote_ident(colname)
|| ' = '
|| quote_literal(newvalue)
|| ' WHERE key = '
|| quote_literal(keyvalue);</PRE
><P>
</P
><P
> This example demonstrates the use of the
<CODE
CLASS="FUNCTION"
>quote_ident</CODE
> and
<CODE
CLASS="FUNCTION"
>quote_literal</CODE
> functions (see <A
HREF="functions-string.html"
>Section 9.4</A
>). For safety, expressions containing column
or table identifiers should be passed through
<CODE
CLASS="FUNCTION"
>quote_ident</CODE
> before insertion in a dynamic query.
Expressions containing values that should be literal strings in the
constructed command should be passed through <CODE
CLASS="FUNCTION"
>quote_literal</CODE
>.
These functions take the appropriate steps to return the input text
enclosed in double or single quotes respectively, with any embedded
special characters properly escaped.
</P
><P
> Because <CODE
CLASS="FUNCTION"
>quote_literal</CODE
> is labelled
<TT
CLASS="LITERAL"
>STRICT</TT
>, it will always return null when called with a
null argument. In the above example, if <TT
CLASS="LITERAL"
>newvalue</TT
> or
<TT
CLASS="LITERAL"
>keyvalue</TT
> were null, the entire dynamic query string would
become null, leading to an error from <TT
CLASS="COMMAND"
>EXECUTE</TT
>.
You can avoid this problem by using the <CODE
CLASS="FUNCTION"
>quote_nullable</CODE
>
function, which works the same as <CODE
CLASS="FUNCTION"
>quote_literal</CODE
> except that
when called with a null argument it returns the string <TT
CLASS="LITERAL"
>NULL</TT
>.
For example,
</P><PRE
CLASS="PROGRAMLISTING"
>EXECUTE 'UPDATE tbl SET '
|| quote_ident(colname)
|| ' = '
|| quote_nullable(newvalue)
|| ' WHERE key = '
|| quote_nullable(keyvalue);</PRE
><P>
If you are dealing with values that might be null, you should usually
use <CODE
CLASS="FUNCTION"
>quote_nullable</CODE
> in place of <CODE
CLASS="FUNCTION"
>quote_literal</CODE
>.
</P
><P
> As always, care must be taken to ensure that null values in a query do
not deliver unintended results. For example the <TT
CLASS="LITERAL"
>WHERE</TT
> clause
</P><PRE
CLASS="PROGRAMLISTING"
>'WHERE key = ' || quote_nullable(keyvalue)</PRE
><P>
will never succeed if <TT
CLASS="LITERAL"
>keyvalue</TT
> is null, because the
result of using the equality operator <TT
CLASS="LITERAL"
>=</TT
> with a null operand
is always null. If you wish null to work like an ordinary key value,
you would need to rewrite the above as
</P><PRE
CLASS="PROGRAMLISTING"
>'WHERE key IS NOT DISTINCT FROM ' || quote_nullable(keyvalue)</PRE
><P>
(At present, <TT
CLASS="LITERAL"
>IS NOT DISTINCT FROM</TT
> is handled much less
efficiently than <TT
CLASS="LITERAL"
>=</TT
>, so don't do this unless you must.
See <A
HREF="functions-comparison.html"
>Section 9.2</A
> for
more information on nulls and <TT
CLASS="LITERAL"
>IS DISTINCT</TT
>.)
</P
><P
> Note that dollar quoting is only useful for quoting fixed text.
It would be a very bad idea to try to write this example as:
</P><PRE
CLASS="PROGRAMLISTING"
>EXECUTE 'UPDATE tbl SET '
|| quote_ident(colname)
|| ' = $$'
|| newvalue
|| '$$ WHERE key = '
|| quote_literal(keyvalue);</PRE
><P>
because it would break if the contents of <TT
CLASS="LITERAL"
>newvalue</TT
>
happened to contain <TT
CLASS="LITERAL"
>$$</TT
>. The same objection would
apply to any other dollar-quoting delimiter you might pick.
So, to safely quote text that is not known in advance, you
<SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>must</I
></SPAN
> use <CODE
CLASS="FUNCTION"
>quote_literal</CODE
>,
<CODE
CLASS="FUNCTION"
>quote_nullable</CODE
>, or <CODE
CLASS="FUNCTION"
>quote_ident</CODE
>, as appropriate.
</P
><P
> Dynamic SQL statements can also be safely constructed using the
<CODE
CLASS="FUNCTION"
>format</CODE
> function (see <A
HREF="functions-string.html"
>Section 9.4</A
>). For example:
</P><PRE
CLASS="PROGRAMLISTING"
>EXECUTE format('UPDATE tbl SET %I = %L WHERE key = %L', colname, newvalue, keyvalue);</PRE
><P>
The <CODE
CLASS="FUNCTION"
>format</CODE
> function can be used in conjunction with
the <TT
CLASS="LITERAL"
>USING</TT
> clause:
</P><PRE
CLASS="PROGRAMLISTING"
>EXECUTE format('UPDATE tbl SET %I = $1 WHERE key = $2', colname)
USING newvalue, keyvalue;</PRE
><P>
This form is more efficient, because the parameters
<TT
CLASS="LITERAL"
>newvalue</TT
> and <TT
CLASS="LITERAL"
>keyvalue</TT
> are not
converted to text.
</P
></DIV
><P
> A much larger example of a dynamic command and
<TT
CLASS="COMMAND"
>EXECUTE</TT
> can be seen in <A
HREF="plpgsql-porting.html#PLPGSQL-PORTING-EX2"
>Example 39-8</A
>, which builds and executes a
<TT
CLASS="COMMAND"
>CREATE FUNCTION</TT
> command to define a new function.
</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="PLPGSQL-STATEMENTS-DIAGNOSTICS"
>39.5.5. Obtaining the Result Status</A
></H2
><P
> There are several ways to determine the effect of a command. The
first method is to use the <TT
CLASS="COMMAND"
>GET DIAGNOSTICS</TT
>
command, which has the form:
</P><PRE
CLASS="SYNOPSIS"
>GET [<SPAN
CLASS="OPTIONAL"
> CURRENT </SPAN
>] DIAGNOSTICS <TT
CLASS="REPLACEABLE"
><I
>variable</I
></TT
> = <TT
CLASS="REPLACEABLE"
><I
>item</I
></TT
> [<SPAN
CLASS="OPTIONAL"
> , ... </SPAN
>];</PRE
><P>
This command allows retrieval of system status indicators. Each
<TT
CLASS="REPLACEABLE"
><I
>item</I
></TT
> is a key word identifying a status
value to be assigned to the specified variable (which should be
of the right data type to receive it). The currently available
status items are <TT
CLASS="VARNAME"
>ROW_COUNT</TT
>, the number of rows
processed by the last <ACRONYM
CLASS="ACRONYM"
>SQL</ACRONYM
> command sent to
the <ACRONYM
CLASS="ACRONYM"
>SQL</ACRONYM
> engine, and <TT
CLASS="VARNAME"
>RESULT_OID</TT
>,
the OID of the last row inserted by the most recent
<ACRONYM
CLASS="ACRONYM"
>SQL</ACRONYM
> command. Note that <TT
CLASS="VARNAME"
>RESULT_OID</TT
>
is only useful after an <TT
CLASS="COMMAND"
>INSERT</TT
> command into a
table containing OIDs.
</P
><P
> An example:
</P><PRE
CLASS="PROGRAMLISTING"
>GET DIAGNOSTICS integer_var = ROW_COUNT;</PRE
><P>
</P
><P
> The second method to determine the effects of a command is to check the
special variable named <TT
CLASS="LITERAL"
>FOUND</TT
>, which is of
type <TT
CLASS="TYPE"
>boolean</TT
>. <TT
CLASS="LITERAL"
>FOUND</TT
> starts out
false within each <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> function call.
It is set by each of the following types of statements:
<P
></P
></P><UL
><LI
><P
> A <TT
CLASS="COMMAND"
>SELECT INTO</TT
> statement sets
<TT
CLASS="LITERAL"
>FOUND</TT
> true if a row is assigned, false if no
row is returned.
</P
></LI
><LI
><P
> A <TT
CLASS="COMMAND"
>PERFORM</TT
> statement sets <TT
CLASS="LITERAL"
>FOUND</TT
>
true if it produces (and discards) one or more rows, false if
no row is produced.
</P
></LI
><LI
><P
> <TT
CLASS="COMMAND"
>UPDATE</TT
>, <TT
CLASS="COMMAND"
>INSERT</TT
>, and <TT
CLASS="COMMAND"
>DELETE</TT
>
statements set <TT
CLASS="LITERAL"
>FOUND</TT
> true if at least one
row is affected, false if no row is affected.
</P
></LI
><LI
><P
> A <TT
CLASS="COMMAND"
>FETCH</TT
> statement sets <TT
CLASS="LITERAL"
>FOUND</TT
>
true if it returns a row, false if no row is returned.
</P
></LI
><LI
><P
> A <TT
CLASS="COMMAND"
>MOVE</TT
> statement sets <TT
CLASS="LITERAL"
>FOUND</TT
>
true if it successfully repositions the cursor, false otherwise.
</P
></LI
><LI
><P
> A <TT
CLASS="COMMAND"
>FOR</TT
> or <TT
CLASS="COMMAND"
>FOREACH</TT
> statement sets
<TT
CLASS="LITERAL"
>FOUND</TT
> true
if it iterates one or more times, else false.
<TT
CLASS="LITERAL"
>FOUND</TT
> is set this way when the
loop exits; inside the execution of the loop,
<TT
CLASS="LITERAL"
>FOUND</TT
> is not modified by the
loop statement, although it might be changed by the
execution of other statements within the loop body.
</P
></LI
><LI
><P
> <TT
CLASS="COMMAND"
>RETURN QUERY</TT
> and <TT
CLASS="COMMAND"
>RETURN QUERY
EXECUTE</TT
> statements set <TT
CLASS="LITERAL"
>FOUND</TT
>
true if the query returns at least one row, false if no row
is returned.
</P
></LI
></UL
><P>
Other <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> statements do not change
the state of <TT
CLASS="LITERAL"
>FOUND</TT
>.
Note in particular that <TT
CLASS="COMMAND"
>EXECUTE</TT
>
changes the output of <TT
CLASS="COMMAND"
>GET DIAGNOSTICS</TT
>, but
does not change <TT
CLASS="LITERAL"
>FOUND</TT
>.
</P
><P
> <TT
CLASS="LITERAL"
>FOUND</TT
> is a local variable within each
<SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> function; any changes to it
affect only the current function.
</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="PLPGSQL-STATEMENTS-NULL"
>39.5.6. Doing Nothing At All</A
></H2
><P
> Sometimes a placeholder statement that does nothing is useful.
For example, it can indicate that one arm of an if/then/else
chain is deliberately empty. For this purpose, use the
<TT
CLASS="COMMAND"
>NULL</TT
> statement:
</P><PRE
CLASS="SYNOPSIS"
>NULL;</PRE
><P>
</P
><P
> For example, the following two fragments of code are equivalent:
</P><PRE
CLASS="PROGRAMLISTING"
>BEGIN
y := x / 0;
EXCEPTION
WHEN division_by_zero THEN
NULL; -- ignore the error
END;</PRE
><P>
</P><PRE
CLASS="PROGRAMLISTING"
>BEGIN
y := x / 0;
EXCEPTION
WHEN division_by_zero THEN -- ignore the error
END;</PRE
><P>
Which is preferable is a matter of taste.
</P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
> In Oracle's PL/SQL, empty statement lists are not allowed, and so
<TT
CLASS="COMMAND"
>NULL</TT
> statements are <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>required</I
></SPAN
> for situations
such as this. <SPAN
CLASS="APPLICATION"
>PL/pgSQL</SPAN
> allows you to
just write nothing, instead.
</P
></BLOCKQUOTE
></DIV
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="plpgsql-expressions.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="plpgsql-control-structures.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Expressions</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="plpgsql.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Control Structures</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>