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:
<programlisting>
EXECUTE 'SELECT count(*) FROM '
|| quote_ident(tabname)
|| ' WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;
</programlisting>
A cleaner approach is to use <function>format()</function>'s <literal>%I</literal>
specification to insert table or column names with automatic quoting:
<programlisting>
EXECUTE format('SELECT count(*) FROM %I '
'WHERE inserted_by = $1 AND inserted <= $2', tabname)
INTO c
USING checked_user, checked_date;
</programlisting>
(This example relies on the SQL rule that string literals separated by a
newline are implicitly concatenated.)
</para>
<para>
Another restriction on parameter symbols is that they only work in
optimizable SQL commands
(<command>SELECT</command>, <command>INSERT</command>, <command>UPDATE</command>,
<command>DELETE</command>, <command>MERGE</command>, and certain commands containing one of these).
In other statement
types (generically called utility statements), you must insert
values textually even if they are just data values.
</para>
<para>
An <command>EXECUTE</command> with a simple constant command string and some
<literal>USING</literal> parameters, as in the first example above, is
functionally equivalent to just writing the command directly in
<application>PL/pgSQL</application> and allowing replacement of
<application>PL/pgSQL</application> variables to happen automatically.
The important difference is that <command>EXECUTE</command> will re-plan
the command on each execution, generating a plan that is specific
to the current parameter values; whereas
<application>PL/pgSQL</application> 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
<command>EXECUTE</command> to positively ensure that a generic plan is not
selected.
</para>
<para>
<command>SELECT INTO</command> is not currently supported within
<command>EXECUTE</command>; instead, execute a plain <command>SELECT</command>
command and specify <literal>INTO</literal> as part of the <command>EXECUTE</command>
itself.
</para>
<note>
<para>
The <application>PL/pgSQL</application>
<command>EXECUTE</command> statement is not related to the
<link linkend="sql-execute"><command>EXECUTE</command></link> SQL
statement supported by the
<productname>PostgreSQL</productname> server. The server's
<command>EXECUTE</command> statement cannot be used directly within
<application>PL/pgSQL</application> functions (and is not needed).
</para>
</note>
<example id="plpgsql-quote-literal-example">
<title>Quoting Values in Dynamic Queries</title>
<indexterm>
<primary>quote_ident</primary>
<secondary>use in PL/pgSQL</secondary>
</indexterm>
<indexterm>
<primary>quote_literal</primary>
<secondary>use in PL/pgSQL</secondary>
</indexterm>
<indexterm>
<primary>quote_nullable</primary>
<secondary>use in PL/pgSQL</secondary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>use in PL/pgSQL</secondary>
</indexterm>
<para>
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 <xref linkend="plpgsql-quote-tips"/>, which can save you
some