summaryrefslogtreecommitdiffstats
path: root/doc/src/sgml/html/plpgsql-development-tips.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/sgml/html/plpgsql-development-tips.html')
-rw-r--r--doc/src/sgml/html/plpgsql-development-tips.html228
1 files changed, 228 insertions, 0 deletions
diff --git a/doc/src/sgml/html/plpgsql-development-tips.html b/doc/src/sgml/html/plpgsql-development-tips.html
new file mode 100644
index 0000000..4176865
--- /dev/null
+++ b/doc/src/sgml/html/plpgsql-development-tips.html
@@ -0,0 +1,228 @@
+<?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>43.12. Tips for Developing in PL/pgSQL</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="plpgsql-implementation.html" title="43.11. PL/pgSQL under the Hood" /><link rel="next" href="plpgsql-porting.html" title="43.13. Porting from Oracle PL/SQL" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">43.12. Tips for Developing in <span class="application">PL/pgSQL</span></th></tr><tr><td width="10%" align="left"><a accesskey="p" href="plpgsql-implementation.html" title="43.11. PL/pgSQL under the Hood">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="plpgsql.html" title="Chapter 43. PL/pgSQL — SQL Procedural Language">Up</a></td><th width="60%" align="center">Chapter 43. <span class="application">PL/pgSQL</span> — <acronym class="acronym">SQL</acronym> Procedural Language</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 16.2 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="plpgsql-porting.html" title="43.13. Porting from Oracle PL/SQL">Next</a></td></tr></table><hr /></div><div class="sect1" id="PLPGSQL-DEVELOPMENT-TIPS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">43.12. Tips for Developing in <span class="application">PL/pgSQL</span> <a href="#PLPGSQL-DEVELOPMENT-TIPS" class="id_link">#</a></h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="plpgsql-development-tips.html#PLPGSQL-QUOTE-TIPS">43.12.1. Handling of Quotation Marks</a></span></dt><dt><span class="sect2"><a href="plpgsql-development-tips.html#PLPGSQL-EXTRA-CHECKS">43.12.2. Additional Compile-Time and Run-Time Checks</a></span></dt></dl></div><p>
+ One good way to develop in
+ <span class="application">PL/pgSQL</span> is to use the text editor of your
+ choice to create your functions, and in another window, use
+ <span class="application">psql</span> to load and test those functions.
+ If you are doing it this way, it
+ is a good idea to write the function using <code class="command">CREATE OR
+ REPLACE FUNCTION</code>. That way you can just reload the file to update
+ the function definition. For example:
+</p><pre class="programlisting">
+CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $$
+ ....
+$$ LANGUAGE plpgsql;
+</pre><p>
+ </p><p>
+ While running <span class="application">psql</span>, you can load or reload such
+ a function definition file with:
+</p><pre class="programlisting">
+\i filename.sql
+</pre><p>
+ and then immediately issue SQL commands to test the function.
+ </p><p>
+ Another good way to develop in <span class="application">PL/pgSQL</span> is with a
+ GUI database access tool that facilitates development in a
+ procedural language. One example of such a tool is
+ <span class="application">pgAdmin</span>, although others exist. These tools often
+ provide convenient features such as escaping single quotes and
+ making it easier to recreate and debug functions.
+ </p><div class="sect2" id="PLPGSQL-QUOTE-TIPS"><div class="titlepage"><div><div><h3 class="title">43.12.1. Handling of Quotation Marks <a href="#PLPGSQL-QUOTE-TIPS" class="id_link">#</a></h3></div></div></div><p>
+ The code of a <span class="application">PL/pgSQL</span> function is specified in
+ <code class="command">CREATE FUNCTION</code> as a string literal. If you
+ write the string literal in the ordinary way with surrounding
+ single quotes, then any single quotes inside the function body
+ must be doubled; likewise any backslashes must be doubled (assuming
+ escape string syntax is used).
+ Doubling quotes is at best tedious, and in more complicated cases
+ the code can become downright incomprehensible, because you can
+ easily find yourself needing half a dozen or more adjacent quote marks.
+ It's recommended that you instead write the function body as a
+ <span class="quote">“<span class="quote">dollar-quoted</span>”</span> string literal (see <a class="xref" href="sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING" title="4.1.2.4. Dollar-Quoted String Constants">Section 4.1.2.4</a>). In the dollar-quoting
+ approach, you never double any quote marks, but instead take care to
+ choose a different dollar-quoting delimiter for each level of
+ nesting you need. For example, you might write the <code class="command">CREATE
+ FUNCTION</code> command as:
+</p><pre class="programlisting">
+CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$
+ ....
+$PROC$ LANGUAGE plpgsql;
+</pre><p>
+ Within this, you might use quote marks for simple literal strings in
+ SQL commands and <code class="literal">$$</code> to delimit fragments of SQL commands
+ that you are assembling as strings. If you need to quote text that
+ includes <code class="literal">$$</code>, you could use <code class="literal">$Q$</code>, and so on.
+ </p><p>
+ The following chart shows what you have to do when writing quote
+ marks without dollar quoting. It might be useful when translating
+ pre-dollar quoting code into something more comprehensible.
+ </p><div class="variablelist"><dl class="variablelist"><dt id="PLPGSQL-QUOTE-TIPS-1-QUOT"><span class="term">1 quotation mark</span> <a href="#PLPGSQL-QUOTE-TIPS-1-QUOT" class="id_link">#</a></dt><dd><p>
+ To begin and end the function body, for example:
+</p><pre class="programlisting">
+CREATE FUNCTION foo() RETURNS integer AS '
+ ....
+' LANGUAGE plpgsql;
+</pre><p>
+ Anywhere within a single-quoted function body, quote marks
+ <span class="emphasis"><em>must</em></span> appear in pairs.
+ </p></dd><dt id="PLPGSQL-QUOTE-TIPS-2-QUOT"><span class="term">2 quotation marks</span> <a href="#PLPGSQL-QUOTE-TIPS-2-QUOT" class="id_link">#</a></dt><dd><p>
+ For string literals inside the function body, for example:
+</p><pre class="programlisting">
+a_output := ''Blah'';
+SELECT * FROM users WHERE f_name=''foobar'';
+</pre><p>
+ In the dollar-quoting approach, you'd just write:
+</p><pre class="programlisting">
+a_output := 'Blah';
+SELECT * FROM users WHERE f_name='foobar';
+</pre><p>
+ which is exactly what the <span class="application">PL/pgSQL</span> parser would see
+ in either case.
+ </p></dd><dt id="PLPGSQL-QUOTE-TIPS-4-QUOT"><span class="term">4 quotation marks</span> <a href="#PLPGSQL-QUOTE-TIPS-4-QUOT" class="id_link">#</a></dt><dd><p>
+ When you need a single quotation mark in a string constant inside the
+ function body, for example:
+</p><pre class="programlisting">
+a_output := a_output || '' AND name LIKE ''''foobar'''' AND xyz''
+</pre><p>
+ The value actually appended to <code class="literal">a_output</code> would be:
+ <code class="literal"> AND name LIKE 'foobar' AND xyz</code>.
+ </p><p>
+ In the dollar-quoting approach, you'd write:
+</p><pre class="programlisting">
+a_output := a_output || $$ AND name LIKE 'foobar' AND xyz$$
+</pre><p>
+ being careful that any dollar-quote delimiters around this are not
+ just <code class="literal">$$</code>.
+ </p></dd><dt id="PLPGSQL-QUOTE-TIPS-6-QUOT"><span class="term">6 quotation marks</span> <a href="#PLPGSQL-QUOTE-TIPS-6-QUOT" class="id_link">#</a></dt><dd><p>
+ When a single quotation mark in a string inside the function body is
+ adjacent to the end of that string constant, for example:
+</p><pre class="programlisting">
+a_output := a_output || '' AND name LIKE ''''foobar''''''
+</pre><p>
+ The value appended to <code class="literal">a_output</code> would then be:
+ <code class="literal"> AND name LIKE 'foobar'</code>.
+ </p><p>
+ In the dollar-quoting approach, this becomes:
+</p><pre class="programlisting">
+a_output := a_output || $$ AND name LIKE 'foobar'$$
+</pre><p>
+ </p></dd><dt id="PLPGSQL-QUOTE-TIPS-10-QUOT"><span class="term">10 quotation marks</span> <a href="#PLPGSQL-QUOTE-TIPS-10-QUOT" class="id_link">#</a></dt><dd><p>
+ When you want two single quotation marks in a string constant (which
+ accounts for 8 quotation marks) and this is adjacent to the end of that
+ string constant (2 more). You will probably only need that if
+ you are writing a function that generates other functions, as in
+ <a class="xref" href="plpgsql-porting.html#PLPGSQL-PORTING-EX2" title="Example 43.10. Porting a Function that Creates Another Function from PL/SQL to PL/pgSQL">Example 43.10</a>.
+ For example:
+</p><pre class="programlisting">
+a_output := a_output || '' if v_'' ||
+ referrer_keys.kind || '' like ''''''''''
+ || referrer_keys.key_string || ''''''''''
+ then return '''''' || referrer_keys.referrer_type
+ || ''''''; end if;'';
+</pre><p>
+ The value of <code class="literal">a_output</code> would then be:
+</p><pre class="programlisting">
+if v_... like ''...'' then return ''...''; end if;
+</pre><p>
+ </p><p>
+ In the dollar-quoting approach, this becomes:
+</p><pre class="programlisting">
+a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like '$$
+ || referrer_keys.key_string || $$'
+ then return '$$ || referrer_keys.referrer_type
+ || $$'; end if;$$;
+</pre><p>
+ where we assume we only need to put single quote marks into
+ <code class="literal">a_output</code>, because it will be re-quoted before use.
+ </p></dd></dl></div></div><div class="sect2" id="PLPGSQL-EXTRA-CHECKS"><div class="titlepage"><div><div><h3 class="title">43.12.2. Additional Compile-Time and Run-Time Checks <a href="#PLPGSQL-EXTRA-CHECKS" class="id_link">#</a></h3></div></div></div><p>
+ To aid the user in finding instances of simple but common problems before
+ they cause harm, <span class="application">PL/pgSQL</span> provides additional
+ <em class="replaceable"><code>checks</code></em>. When enabled, depending on the configuration, they
+ can be used to emit either a <code class="literal">WARNING</code> or an <code class="literal">ERROR</code>
+ during the compilation of a function. A function which has received
+ a <code class="literal">WARNING</code> can be executed without producing further messages,
+ so you are advised to test in a separate development environment.
+ </p><p>
+ Setting <code class="varname">plpgsql.extra_warnings</code>, or
+ <code class="varname">plpgsql.extra_errors</code>, as appropriate, to <code class="literal">"all"</code>
+ is encouraged in development and/or testing environments.
+ </p><p>
+ These additional checks are enabled through the configuration variables
+ <code class="varname">plpgsql.extra_warnings</code> for warnings and
+ <code class="varname">plpgsql.extra_errors</code> for errors. Both can be set either to
+ a comma-separated list of checks, <code class="literal">"none"</code> or
+ <code class="literal">"all"</code>. The default is <code class="literal">"none"</code>. Currently
+ the list of available checks includes:
+ </p><div class="variablelist"><dl class="variablelist"><dt id="PLPGSQL-EXTRA-CHECKS-SHADOWED-VARIABLES"><span class="term"><code class="varname">shadowed_variables</code></span> <a href="#PLPGSQL-EXTRA-CHECKS-SHADOWED-VARIABLES" class="id_link">#</a></dt><dd><p>
+ Checks if a declaration shadows a previously defined variable.
+ </p></dd><dt id="PLPGSQL-EXTRA-CHECKS-STRICT-MULTI-ASSIGNMENT"><span class="term"><code class="varname">strict_multi_assignment</code></span> <a href="#PLPGSQL-EXTRA-CHECKS-STRICT-MULTI-ASSIGNMENT" class="id_link">#</a></dt><dd><p>
+ Some <span class="application">PL/pgSQL</span> commands allow assigning
+ values to more than one variable at a time, such as
+ <code class="command">SELECT INTO</code>. Typically, the number of target
+ variables and the number of source variables should match, though
+ <span class="application">PL/pgSQL</span> will use <code class="literal">NULL</code>
+ for missing values and extra variables are ignored. Enabling this
+ check will cause <span class="application">PL/pgSQL</span> to throw a
+ <code class="literal">WARNING</code> or <code class="literal">ERROR</code> whenever the
+ number of target variables and the number of source variables are
+ different.
+ </p></dd><dt id="PLPGSQL-EXTRA-CHECKS-TOO-MANY-ROWS"><span class="term"><code class="varname">too_many_rows</code></span> <a href="#PLPGSQL-EXTRA-CHECKS-TOO-MANY-ROWS" class="id_link">#</a></dt><dd><p>
+ Enabling this check will cause <span class="application">PL/pgSQL</span> to
+ check if a given query returns more than one row when an
+ <code class="literal">INTO</code> clause is used. As an <code class="literal">INTO</code>
+ statement will only ever use one row, having a query return multiple
+ rows is generally either inefficient and/or nondeterministic and
+ therefore is likely an error.
+ </p></dd></dl></div><p>
+
+ The following example shows the effect of <code class="varname">plpgsql.extra_warnings</code>
+ set to <code class="varname">shadowed_variables</code>:
+</p><pre class="programlisting">
+SET plpgsql.extra_warnings TO 'shadowed_variables';
+
+CREATE FUNCTION foo(f1 int) RETURNS int AS $$
+DECLARE
+f1 int;
+BEGIN
+RETURN f1;
+END;
+$$ LANGUAGE plpgsql;
+WARNING: variable "f1" shadows a previously defined variable
+LINE 3: f1 int;
+ ^
+CREATE FUNCTION
+</pre><p>
+ The below example shows the effects of setting
+ <code class="varname">plpgsql.extra_warnings</code> to
+ <code class="varname">strict_multi_assignment</code>:
+</p><pre class="programlisting">
+SET plpgsql.extra_warnings TO 'strict_multi_assignment';
+
+CREATE OR REPLACE FUNCTION public.foo()
+ RETURNS void
+ LANGUAGE plpgsql
+AS $$
+DECLARE
+ x int;
+ y int;
+BEGIN
+ SELECT 1 INTO x, y;
+ SELECT 1, 2 INTO x, y;
+ SELECT 1, 2, 3 INTO x, y;
+END;
+$$;
+
+SELECT foo();
+WARNING: number of source and target fields in assignment does not match
+DETAIL: strict_multi_assignment check of extra_warnings is active.
+HINT: Make sure the query returns the exact list of columns.
+WARNING: number of source and target fields in assignment does not match
+DETAIL: strict_multi_assignment check of extra_warnings is active.
+HINT: Make sure the query returns the exact list of columns.
+
+ foo
+-----
+
+(1 row)
+</pre><p>
+ </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="plpgsql-implementation.html" title="43.11. PL/pgSQL under the Hood">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="plpgsql.html" title="Chapter 43. PL/pgSQL — SQL Procedural Language">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="plpgsql-porting.html" title="43.13. Porting from Oracle PL/SQL">Next</a></td></tr><tr><td width="40%" align="left" valign="top">43.11. <span class="application">PL/pgSQL</span> under the Hood </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 16.2 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 43.13. Porting from <span class="productname">Oracle</span> PL/SQL</td></tr></table></div></body></html> \ No newline at end of file