mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
Some PL/PgSQL documentation improvements from Neil Conway.
This commit is contained in:
parent
c91b8bc537
commit
1b69b122bb
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.6 2002/09/01 16:28:05 tgl Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.7 2002/09/14 20:11:16 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="plpgsql">
|
||||
@ -70,18 +70,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v 1.6 2002/09/01 16:28:05 tgl
|
||||
</para>
|
||||
<para>
|
||||
As each expression and <acronym>SQL</acronym> query is first used
|
||||
in the function, the <application>PL/pgSQL</> interpreter creates a
|
||||
prepared execution plan (using the <acronym>SPI</acronym> manager's
|
||||
<function>SPI_prepare</function> and
|
||||
<function>SPI_saveplan</function> functions). Subsequent visits
|
||||
to that expression or query re-use the prepared plan. Thus, a function
|
||||
with conditional code that contains many statements for which execution
|
||||
plans might be required, will only prepare and save those plans
|
||||
that are really used during the lifetime of the database
|
||||
connection. This can provide a considerable savings of parsing
|
||||
activity. A disadvantage is that errors in a specific expression
|
||||
or query may not be detected until that part of the function is
|
||||
reached in execution.
|
||||
in the function, the <application>PL/pgSQL</> interpreter creates
|
||||
a prepared execution plan (using the <acronym>SPI</acronym>
|
||||
manager's <function>SPI_prepare</function> and
|
||||
<function>SPI_saveplan</function> functions). Subsequent visits
|
||||
to that expression or query re-use the prepared plan. Thus, a
|
||||
function with conditional code that contains many statements for
|
||||
which execution plans might be required will only prepare and save
|
||||
those plans that are really used during the lifetime of the
|
||||
database connection. This can substantially reduce the total
|
||||
amount of time required to parse, and generate query plans for the
|
||||
statements in a procedural language function. A disadvantage is
|
||||
that errors in a specific expression or query may not be detected
|
||||
until that part of the function is reached in execution.
|
||||
</para>
|
||||
<para>
|
||||
Once <application>PL/pgSQL</> has made a query plan for a particular
|
||||
@ -110,14 +111,26 @@ END;
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Because <application>PL/pgSQL</application> saves execution plans in this way, queries that appear
|
||||
directly in a <application>PL/pgSQL</application> function must refer to the same tables and fields
|
||||
on every execution; that is, you cannot use a parameter as the name of
|
||||
a table or field in a query. To get around
|
||||
this restriction, you can construct dynamic queries using the <application>PL/pgSQL</application>
|
||||
EXECUTE statement --- at the price of constructing a new query plan
|
||||
on every execution.
|
||||
Because <application>PL/pgSQL</application> saves execution plans
|
||||
in this way, queries that appear directly in a
|
||||
<application>PL/pgSQL</application> function must refer to the
|
||||
same tables and fields on every execution; that is, you cannot use
|
||||
a parameter as the name of a table or field in a query. To get
|
||||
around this restriction, you can construct dynamic queries using
|
||||
the <application>PL/pgSQL</application> EXECUTE statement --- at
|
||||
the price of constructing a new query plan on every execution.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
The <application>PL/pgSQL</application> EXECUTE statement is not
|
||||
related to the EXECUTE statement supported by the
|
||||
<productname>PostgreSQL</productname> backend. The backend
|
||||
EXECUTE statement cannot be used within PL/PgSQL functions (and
|
||||
is not needed).
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Except for input/output conversion and calculation functions
|
||||
for user defined types, anything that can be defined in C language
|
||||
@ -152,11 +165,11 @@ END;
|
||||
<title>Better Performance</title>
|
||||
|
||||
<para>
|
||||
<acronym>SQL</acronym> is the language <productname>PostgreSQL</> (and
|
||||
most other Relational Databases) use as query
|
||||
language. It's portable and easy to learn. But every
|
||||
<acronym>SQL</acronym> statement must be executed
|
||||
individually by the database server.
|
||||
<acronym>SQL</acronym> is the language
|
||||
<productname>PostgreSQL</> (and most other relational databases)
|
||||
use as query language. It's portable and easy to learn. But
|
||||
every <acronym>SQL</acronym> statement must be executed
|
||||
individually by the database server.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -195,9 +208,10 @@ END;
|
||||
<title>Portability</title>
|
||||
|
||||
<para>
|
||||
Because <application>PL/pgSQL</application> functions run inside <productname>PostgreSQL</>, these
|
||||
functions will run on any platform where <productname>PostgreSQL</>
|
||||
runs. Thus you can reuse code and have less development costs.
|
||||
Because <application>PL/pgSQL</application> functions run inside
|
||||
<productname>PostgreSQL</>, these functions will run on any
|
||||
platform where <productname>PostgreSQL</> runs. Thus you can
|
||||
reuse code and reduce development costs.
|
||||
</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
@ -227,16 +241,17 @@ END;
|
||||
</para>
|
||||
|
||||
<para>
|
||||
One good way to develop in <application>PL/pgSQL</> is to simply use the text
|
||||
editor of your choice to create your functions, and in another
|
||||
console, use <command>psql</command> (PostgreSQL's interactive monitor) to load
|
||||
those functions. If you are doing it this way, it is a good
|
||||
idea to write the function using <command>CREATE OR REPLACE
|
||||
FUNCTION</command>. That way you can reload the file to update
|
||||
the function definition. For example:
|
||||
One good way to develop in <application>PL/pgSQL</> is to simply
|
||||
use the text editor of your choice to create your functions, and
|
||||
in another window, use <command>psql</command>
|
||||
(<productname>PostgreSQL</>'s interactive monitor) to load those
|
||||
functions. If you are doing it this way, it is a good idea to
|
||||
write the function using <command>CREATE OR REPLACE
|
||||
FUNCTION</>. That way you can reload the file to update the
|
||||
function definition. For example:
|
||||
<programlisting>
|
||||
CREATE OR REPLACE FUNCTION testfunc(INTEGER) RETURNS INTEGER AS '
|
||||
....
|
||||
....
|
||||
end;
|
||||
' LANGUAGE 'plpgsql';
|
||||
</programlisting>
|
||||
@ -645,9 +660,9 @@ RENAME this_var TO that_var;
|
||||
|
||||
<note>
|
||||
<para>
|
||||
RENAME appears to be broken as of PostgreSQL 7.2. Fixing this is
|
||||
of low priority, since ALIAS covers most of the practical uses of
|
||||
RENAME.
|
||||
RENAME appears to be broken as of <productname>PostgreSQL</>
|
||||
7.3. Fixing this is of low priority, since ALIAS covers most of
|
||||
the practical uses of RENAME.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
@ -898,7 +913,7 @@ END;
|
||||
PERFORM <replaceable>query</replaceable>;
|
||||
</synopsis>
|
||||
|
||||
This executes a <literal>SELECT</literal>
|
||||
This executes a <command>SELECT</command>
|
||||
<replaceable>query</replaceable> and discards the
|
||||
result. <application>PL/pgSQL</application> variables are
|
||||
substituted in the query as usual. Also, the special variable
|
||||
@ -1044,6 +1059,10 @@ END;
|
||||
<title>Obtaining result status</title>
|
||||
|
||||
<para>
|
||||
There are several ways to determine the effect of a command. The
|
||||
first method is to use the <literal>GET DIAGNOSTICS</literal>,
|
||||
which has the form:
|
||||
|
||||
<synopsis>
|
||||
GET DIAGNOSTICS <replaceable>variable</replaceable> = <replaceable>item</replaceable> <optional> , ... </optional> ;
|
||||
</synopsis>
|
||||
@ -1166,10 +1185,19 @@ RETURN <replaceable>expression</replaceable>;
|
||||
<para>
|
||||
When a <application>PL/pgSQL</> function is declared to return
|
||||
<literal>SETOF</literal> <replaceable>sometype</>, the procedure
|
||||
to follow is slightly different. The individual items to be returned
|
||||
are specified in RETURN NEXT commands, and then a final RETURN with
|
||||
no argument is given to indicate that the function is done generating
|
||||
items.
|
||||
to follow is slightly different. In that case, the individual
|
||||
items to return are specified in RETURN NEXT commands, and then a
|
||||
final RETURN command with no arguments is used to indicate that
|
||||
the function has finished executing. RETURN NEXT can be used with
|
||||
both scalar and composite data types; in the later case, an
|
||||
entire "table" of results will be returned. Functions that use
|
||||
RETURN NEXT should be called in the following fashion:
|
||||
|
||||
<programlisting>
|
||||
SELECT * FROM some_func();
|
||||
</programlisting>
|
||||
|
||||
That is, the function is used as a table source in a FROM clause.
|
||||
|
||||
<synopsis>
|
||||
RETURN NEXT <replaceable>expression</replaceable>;
|
||||
@ -1184,6 +1212,24 @@ RETURN NEXT <replaceable>expression</replaceable>;
|
||||
RETURN, which need have no argument, causes control to exit
|
||||
the function.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
The current implementation of RETURN NEXT for PL/PgSQL stores
|
||||
the entire result set before returning from the function, as
|
||||
discussed above. That means that if a PL/PgSQL function
|
||||
produces a very large result set, performance may be poor: data
|
||||
will be written to disk to avoid memory exhaustion, but the
|
||||
function itself will not return until the entire
|
||||
result set has been generated. A future version of PL/PgSQL may
|
||||
allow users to allow users to define set-returning functions
|
||||
that do not have this limitation. Currently, the point at which
|
||||
data begins being written to disk is controlled by the
|
||||
<option>SORT_MEM</> configuration variable. Administrators who
|
||||
have sufficient memory to store larger result sets in memory
|
||||
should consider increasing this parameter.
|
||||
</para>
|
||||
</note>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="plpgsql-conditionals">
|
||||
@ -1904,13 +1950,14 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
|
||||
<title>Trigger Procedures</title>
|
||||
|
||||
<para>
|
||||
<application>PL/pgSQL</application> can be used to define trigger
|
||||
procedures. A trigger procedure is created with the <command>CREATE
|
||||
FUNCTION</command> command as a function with no arguments and a return
|
||||
type of <type>TRIGGER</type>. Note that the function must be declared
|
||||
with no arguments even if it expects to receive arguments specified
|
||||
in <command>CREATE TRIGGER</> --- trigger arguments are passed via
|
||||
<varname>TG_ARGV</>, as described below.
|
||||
<application>PL/pgSQL</application> can be used to define trigger
|
||||
procedures. A trigger procedure is created with the
|
||||
<command>CREATE FUNCTION</> command as a function with no
|
||||
arguments and a return type of <type>TRIGGER</type>. Note that
|
||||
the function must be declared with no arguments even if it expects
|
||||
to receive arguments specified in <command>CREATE TRIGGER</> ---
|
||||
trigger arguments are passed via <varname>TG_ARGV</>, as described
|
||||
below.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -2106,14 +2153,15 @@ CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
|
||||
</para>
|
||||
|
||||
<para>
|
||||
One painful detail in writing functions in <application>PL/pgSQL</application> is the handling
|
||||
of single quotes. The function's source text in <command>CREATE FUNCTION</command> must
|
||||
be a literal string. Single quotes inside of literal strings must be
|
||||
either doubled or quoted with a backslash. We are still looking for
|
||||
an elegant alternative. In the meantime, doubling the single quotes
|
||||
as in the examples below should be used. Any solution for this
|
||||
in future versions of <productname>PostgreSQL</productname> will be
|
||||
forward compatible.
|
||||
One painful detail in writing functions in
|
||||
<application>PL/pgSQL</application> is the handling of single
|
||||
quotes. The function's source text in <command>CREATE FUNCTION</>
|
||||
must be a literal string. Single quotes inside of literal strings
|
||||
must be either doubled or quoted with a backslash. We are still
|
||||
looking for an elegant alternative. In the meantime, doubling the
|
||||
single quotes as in the examples below should be used. Any
|
||||
solution for this in future versions of
|
||||
<productname>PostgreSQL</productname> will be forward compatible.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -2504,7 +2552,7 @@ END;
|
||||
|
||||
<para>
|
||||
The following procedure grabs rows from a
|
||||
<literal>SELECT</literal> statement and builds a large function
|
||||
<command>SELECT</command> statement and builds a large function
|
||||
with the results in <literal>IF</literal> statements, for the
|
||||
sake of efficiency. Notice particularly the differences in
|
||||
cursors, <literal>FOR</literal> loops, and the need to escape
|
||||
@ -2735,7 +2783,7 @@ show errors
|
||||
|
||||
<callout arearefs="co.plpgsql-porting-locktable">
|
||||
<para>
|
||||
If you do a <literal>LOCK TABLE</literal> in <application>PL/pgSQL</>, the lock
|
||||
If you do a <command>LOCK TABLE</command> in <application>PL/pgSQL</>, the lock
|
||||
will not be released until the calling transaction is finished.
|
||||
</para>
|
||||
</callout>
|
||||
@ -2746,7 +2794,7 @@ show errors
|
||||
entire function (and other functions called from therein) is
|
||||
executed in a transaction and <productname>PostgreSQL</> rolls back the results if
|
||||
something goes wrong. Therefore only one
|
||||
<literal>BEGIN</literal> statement is allowed.
|
||||
<command>BEGIN</command> statement is allowed.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
@ -2895,7 +2943,7 @@ END;
|
||||
<title>EXECUTE</title>
|
||||
|
||||
<para>
|
||||
The <productname>PostgreSQL</> version of <literal>EXECUTE</literal> works
|
||||
The <productname>PostgreSQL</> version of <command>EXECUTE</command> works
|
||||
nicely, but you have to remember to use
|
||||
<function>quote_literal(TEXT)</function> and
|
||||
<function>quote_string(TEXT)</function> as described in <xref
|
||||
|
Loading…
Reference in New Issue
Block a user