<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>OpenText Analytics Database 26.2.x – PL/vSQL</title>
    <link>/en/extending/stored-procedures/plvsql/</link>
    <description>Recent content in PL/vSQL on OpenText Analytics Database 26.2.x</description>
    <generator>Hugo -- gohugo.io</generator>
    
	  <atom:link href="/en/extending/stored-procedures/plvsql/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Extending: Supported types</title>
      <link>/en/extending/stored-procedures/plvsql/supported-types/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/extending/stored-procedures/plvsql/supported-types/</guid>
      <description>
        
        
        &lt;p&gt;OpenText™ Analytics Database PL/vSQL supports non-complex &lt;a href=&#34;../../../../en/sql-reference/data-types/&#34;&gt;data types&lt;/a&gt;. The following types are supported as &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/scope-and-structure/&#34;&gt;variables&lt;/a&gt; only and not as arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;DECIMAL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NUMERIC&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NUMBER&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MONEY&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UUID&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Extending: Scope and structure</title>
      <link>/en/extending/stored-procedures/plvsql/scope-and-structure/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/extending/stored-procedures/plvsql/scope-and-structure/</guid>
      <description>
        
        
        &lt;p&gt;PL/vSQL uses block scope, where a block has the following structure:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ &amp;lt;&amp;lt;&lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt;&amp;gt;&amp;gt; ]
[ DECLARE
    &lt;span class=&#34;code-variable&#34;&gt;declarations&lt;/span&gt; ]
BEGIN
    &lt;span class=&#34;code-variable&#34;&gt;statements&lt;/span&gt;
    ...
END [ &lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;declarations&#34;&gt;Declarations&lt;/h2&gt;
&lt;p&gt;Variable &lt;em&gt;&lt;code&gt;declarations&lt;/code&gt;&lt;/em&gt; in the DECLARE block are structured as:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;variable_name&lt;/span&gt; [ CONSTANT ] &lt;span class=&#34;code-variable&#34;&gt;data_type&lt;/span&gt; [ NOT NULL ] [:= { &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt; | &lt;span class=&#34;code-variable&#34;&gt;statement&lt;/span&gt; } ];
&lt;/code&gt;&lt;/pre&gt;
&lt;table class=&#34;table table-bordered&#34; &gt;



&lt;tr&gt; 

&lt;td &gt;
&lt;em&gt;&lt;code&gt;variable_name&lt;/code&gt;&lt;/em&gt;&lt;/td&gt; 

&lt;td &gt;








&lt;p&gt;Variable names must meet the following requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Must be &lt;a href=&#34;../../../../en/sql-reference/language-elements/identifiers/&#34;&gt;SQL identifiers&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cannot be &lt;a href=&#34;../../../../en/sql-reference/language-elements/keywords/&#34;&gt;reserved keywords&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cannot duplicate those in previous declarations inside the same block.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;CONSTANT&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Defines the variable as a constant (immutable). You can only set a constant variable&#39;s value during initialization.&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;em&gt;&lt;code&gt;data_type&lt;/code&gt;&lt;/em&gt;&lt;/td&gt; 

&lt;td &gt;










&lt;p&gt;The variable data type. PL/vSQL supports non-complex &lt;a href=&#34;../../../../en/sql-reference/data-types/&#34;&gt;data types&lt;/a&gt;, with the following exceptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;GEOMETRY&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GEOGRAPHY&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can optionally reference a particular column&#39;s data type:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;variable_name&lt;/code&gt;&lt;/em&gt;&lt;code&gt; &lt;/code&gt;&lt;em&gt;&lt;code&gt;table_name.column_name%TYPE&lt;/code&gt;&lt;/em&gt;&lt;code&gt;;&lt;/code&gt;&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;NOT NULL&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;


Specifies that the variable cannot hold a NULL value. If declared with NOT NULL, the variable must be initialized (otherwise, throws ERRCODE_SYNTAX_ERROR) and cannot be assigned NULL (otherwise, throws ERRCODE_WRONG_OBJECT_TYPE).&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;:= &lt;/code&gt;&lt;em&gt;&lt;code&gt;expression&lt;/code&gt;&lt;/em&gt;&lt;/td&gt; 

&lt;td &gt;














&lt;p&gt;Initializes a variable with &lt;em&gt;&lt;code&gt;expression&lt;/code&gt;&lt;/em&gt; or statement.&lt;/p&gt;
&lt;p&gt;If the variable is declared with &lt;code&gt;NOT NULL&lt;/code&gt;, &lt;em&gt;&lt;code&gt;expression&lt;/code&gt;&lt;/em&gt; is required.&lt;/p&gt;
&lt;p&gt;Variable declarations in a given block execute sequentially, so old declarations can be referenced by newer ones. For example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DECLARE
    x int := 3;
    y int := x;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Default&lt;/strong&gt; (uninitialized): NULL&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;h3 id=&#34;aliases&#34;&gt;Aliases&lt;/h3&gt;
&lt;p&gt;Aliases are alternate names for the same variable. An alias of a variable is not a copy, and changes made to either reference affect the same underlying variable.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;new_name&lt;/span&gt; ALIAS FOR &lt;span class=&#34;code-variable&#34;&gt;variable&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here, the identifier &lt;code&gt;y&lt;/code&gt; is now an alias for variable &lt;code&gt;x&lt;/code&gt;, and changes to &lt;code&gt;y&lt;/code&gt; are reflected in &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DO $$
DECLARE
    x int := 3;
    y ALIAS FOR x;
BEGIN
    y := 5; -- since y refers to x, x = 5
    RAISE INFO &amp;#39;x = %, y = %&amp;#39;, x, y;
END;
$$;

INFO 2005:  x = 5, y = 5
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;begin-and-nested-blocks&#34;&gt;BEGIN and nested blocks&lt;/h2&gt;
&lt;p&gt;BEGIN contains &lt;em&gt;&lt;code&gt;statements&lt;/code&gt;&lt;/em&gt;. A &lt;em&gt;statement&lt;/em&gt; is defined as a line or block of PL/vSQL.&lt;/p&gt;
&lt;p&gt;Variables declared in inner blocks &lt;a href=&#34;https://en.wikipedia.org/wiki/Variable_shadowing&#34;&gt;shadow&lt;/a&gt; those declared in outer blocks. To unambiguously specify a variable in a particular block, you can name the block with a &lt;em&gt;&lt;code&gt;label&lt;/code&gt;&lt;/em&gt; (case-insensitive), and then reference the variable declared in that block with:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt;.&lt;span class=&#34;code-variable&#34;&gt;variable_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, specifying the variable &lt;code&gt;x&lt;/code&gt; from inside the inner block implicitly refers to &lt;code&gt;inner_block.x&lt;/code&gt; rather than &lt;code&gt;outer_block.x&lt;/code&gt; because of shadowing:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;
&amp;lt;&amp;lt;outer_block&amp;gt;&amp;gt;
DECLARE
    x int;
BEGIN
    &amp;lt;&amp;lt;inner_block&amp;gt;&amp;gt;
    DECLARE
        x int;
    BEGIN
        x := 1000; -- implicitly specifies x in inner_block because of shadowing
        OUTER_BLOCK.x := 0; -- specifies x in outer_block; labels are case-insensitive
    END inner_block;
END outer_block;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;null-statement&#34;&gt;NULL statement&lt;/h2&gt;
&lt;p&gt;The NULL statement does nothing. This can be useful as a placeholder statement or a way to show that a code block is intentionally empty. For example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DO $$
BEGIN
    NULL;
END;
$$
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;comments&#34;&gt;Comments&lt;/h2&gt;
&lt;p&gt;Comments have the following syntax. You cannot nest comments.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-- single-line comment

/* multi-line
comment
*/
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;nested-stored-procedures&#34;&gt;Nested stored procedures&lt;/h2&gt;
&lt;p&gt;Stored procedures that call other stored procedures, also called nested stored procedures, can be useful for simplifying complex functions and reusing code.&lt;/p&gt;
&lt;p&gt;You can enable nested stored procedures by setting the EnableNestedStoredProcedures configuration parameter (disabled by default):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;--Enable nested calls
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ALTER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DATABASE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DEFAULT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SET&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EnableNestedStoredProcedures&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;--Disable nested calls
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ALTER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DATABASE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DEFAULT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SET&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EnableNestedStoredProcedures&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the following example, &lt;code&gt;proc2()&lt;/code&gt; calls &lt;code&gt;proc1()&lt;/code&gt; to insert values into a table:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;PROCEDURE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;proc1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BEGIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PERFORM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INSERT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INTO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t_int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;VALUES&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2023&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;END&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;PROCEDURE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;proc2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BEGIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PERFORM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;IF&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NOT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;EXISTS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t_int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PERFORM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CALL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;proc1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;END&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can also use this feature to call meta-functions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;PROCEDURE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RUN_ANALYZE_STATS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BEGIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PERFORM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;analyze_statistics&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;END&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CALL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;run_analyze_stats&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;depth-limits&#34;&gt;Depth limits&lt;/h3&gt;
&lt;p&gt;Stored procedures can only be nested up to a depth of 50. If a stored procedure exceeds the call depth, the entire operation is terminated and &lt;a class=&#34;glosslink&#34; href=&#34;../../../../en/glossary/rollback/&#34; title=&#34;&#34;&gt;rolled back&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The stored procedure &lt;code&gt;recursive_proc()&lt;/code&gt; calls itself to insert sequential values into a table, but it has no condition to stop before the depth limit. Calling the procedure causes a rollback and no changes are made to the table:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numbers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;INT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numbers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;OR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;REPLACE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;PROCEDURE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;recursive_proc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BEGIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PERFORM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INSERT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INTO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numbers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;VALUES&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PERFORM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CALL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;recursive_proc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;END&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CALL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;recursive_proc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ERROR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Nested&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stored&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;procedure&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exceeds&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;depth&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;limit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CONTEXT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vSQL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;procedure&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;recursive_proc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SQL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vSQL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;procedure&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;recursive_proc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SQL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vSQL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;procedure&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;recursive_proc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SQL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numbers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
      </description>
    </item>
    
    <item>
      <title>Extending: Embedded SQL</title>
      <link>/en/extending/stored-procedures/plvsql/embedded-sql/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/extending/stored-procedures/plvsql/embedded-sql/</guid>
      <description>
        
        
        &lt;p&gt;You can embed and execute SQL &lt;a class=&#34;glosslink&#34; href=&#34;../../../../en/glossary/statement/&#34; title=&#34;A line of SQL, excluding the semicolon.&#34;&gt;statements&lt;/a&gt; and &lt;a class=&#34;glosslink&#34; href=&#34;../../../../en/glossary/expression/&#34; title=&#34;An expression is anything that can represent a single column in a SELECT statement.&#34;&gt;expressions&lt;/a&gt; from within stored procedures.&lt;/p&gt;
&lt;h2 id=&#34;assignment&#34;&gt;Assignment&lt;/h2&gt;
&lt;p&gt;To save the value of an expression or returned value, you can assign it to a variable:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;variable_name&lt;/span&gt; := &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt;;
&lt;span class=&#34;code-variable&#34;&gt;variable_name&lt;/span&gt; := &lt;span class=&#34;code-variable&#34;&gt;statement&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, this procedure assigns 3 into &lt;code&gt;i&lt;/code&gt; and &#39;message&#39; into &lt;code&gt;v&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; CREATE PROCEDURE performless_assignment() LANGUAGE PLvSQL AS $$
DECLARE
    i int;
    v varchar;
BEGIN
    i := SELECT 3;
    v := &amp;#39;message&amp;#39;;
END;
$$;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This type of assignment will fail if the query returns no rows or more than one row. For returns of multiple rows, use &lt;a href=&#34;../../../../en/sql-reference/statements/select/limit-clause/&#34;&gt;LIMIT&lt;/a&gt; or &lt;a href=&#34;#truncating_assignment&#34;&gt;truncating assignment&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT * FROM t1;
 b
---
 t
 f
 f
(3 rows)


=&amp;gt; CREATE PROCEDURE more_than_one_row() LANGUAGE PLvSQL as $$
DECLARE
    x boolean;
BEGIN
    x := SELECT * FROM t1;
END;
$$;
CREATE PROCEDURE

=&amp;gt; CALL more_than_one_row();
ERROR 10332:  Query returned multiple rows where 1 was expected
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;truncating-assignment&#34;&gt;Truncating assignment&lt;/h3&gt;
&lt;p&gt;Truncating assignment stores in a variable the first row returned by a query. Row order is nondeterministic unless you specify an &lt;a href=&#34;../../../../en/sql-reference/statements/select/order-by-clause/&#34;&gt;ORDER BY clause&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;variable_name&lt;/span&gt; &amp;lt;- &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt;;
&lt;span class=&#34;code-variable&#34;&gt;variable_name&lt;/span&gt; &amp;lt;- &lt;span class=&#34;code-variable&#34;&gt;statement&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following procedure takes the first row of the results returned by the specified query and assigns it to &lt;code&gt;x&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; CREATE PROCEDURE truncating_assignment() LANGUAGE PLvSQL AS $$
DECLARE
    x boolean;
BEGIN
    x &amp;lt;- SELECT * FROM t1 ORDER BY b DESC; -- x is now assigned the first row returned by the SELECT query
END;
$$;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;perform&#34;&gt;PERFORM&lt;/h2&gt;
&lt;p&gt;The PERFORM keyword runs a SQL &lt;a class=&#34;glosslink&#34; href=&#34;../../../../en/glossary/statement/&#34; title=&#34;A line of SQL, excluding the semicolon.&#34;&gt;statement&lt;/a&gt; or &lt;a class=&#34;glosslink&#34; href=&#34;../../../../en/glossary/expression/&#34; title=&#34;An expression is anything that can represent a single column in a SELECT statement.&#34;&gt;expression&lt;/a&gt; and discards the returned result.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;PERFORM &lt;span class=&#34;code-variable&#34;&gt;statement&lt;/span&gt;;
PERFORM &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, this procedure inserts a value into a table. INSERT returns the number of rows inserted, so you must pair it with PERFORM.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
BEGIN
    PERFORM INSERT INTO coordinates VALUES(1,2,3);
END;
$$;
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;alert admonition note&#34; role=&#34;alert&#34;&gt;
&lt;h4 class=&#34;admonition-head&#34;&gt;Note&lt;/h4&gt;

If a SQL statement has no return value or you don&#39;t assign the return value to a variable, you must use PERFORM.

&lt;/div&gt;
&lt;h2 id=&#34;execute&#34;&gt;EXECUTE&lt;/h2&gt;
&lt;p&gt;EXECUTE allows you to dynamically construct a SQL query during execution:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;EXECUTE &lt;span class=&#34;code-variable&#34;&gt;command_expression&lt;/span&gt; [ USING &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt; [, ... ] ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;&lt;code&gt;command_expression&lt;/code&gt;&lt;/em&gt; is a SQL expression that can reference PL/vSQL variables and evaluates to a string literal. The string literal is executed as a SQL statement, and $1, $2, ... are substituted with the corresponding *&lt;code&gt;expression&lt;/code&gt;*s.&lt;/p&gt;
&lt;p&gt;Constructing your query with PL/vSQL variables can be dangerous and expose your system to SQL injection, so wrap them with &lt;a href=&#34;../../../../en/sql-reference/functions/data-type-specific-functions/string-functions/quote-ident/#&#34;&gt;QUOTE_IDENT&lt;/a&gt;, &lt;a href=&#34;../../../../en/sql-reference/functions/data-type-specific-functions/string-functions/quote-literal/#&#34;&gt;QUOTE_LITERAL&lt;/a&gt;, and &lt;a href=&#34;../../../../en/sql-reference/functions/data-type-specific-functions/string-functions/quote-nullable/#&#34;&gt;QUOTE_NULLABLE&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following procedure constructs a query with a WHERE clause:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DO $$
BEGIN
    EXECUTE &amp;#39;SELECT * FROM t1 WHERE x = $1&amp;#39; USING 10; -- becomes WHERE x = 10
END;
$$;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following procedure creates a user with a password from the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; arguments. Because the constructed CREATE USER statement uses variables, use the functions QUOTE_IDENT and QUOTE_LITERAL, &lt;a href=&#34;../../../../en/sql-reference/language-elements/operators/string-concatenation-operators/&#34;&gt;concatenating&lt;/a&gt; them with ||.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; CREATE PROCEDURE create_user(username varchar, password varchar) LANGUAGE PLvSQL AS $$
BEGIN
    EXECUTE &amp;#39;CREATE USER &amp;#39; || QUOTE_IDENT(username) || &amp;#39; IDENTIFIED BY &amp;#39; || QUOTE_LITERAL(password);
END;
$$;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;EXECUTE is a SQL statement, so you can assign it to a variable or pair it with PERFORM:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;variable_name&lt;/span&gt;:= EXECUTE &lt;span class=&#34;code-variable&#34;&gt;command_expression&lt;/span&gt;;
PERFORM EXECUTE &lt;span class=&#34;code-variable&#34;&gt;command_expression&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;found-special-variable&#34;&gt;FOUND (special variable)&lt;/h2&gt;
&lt;p&gt;The special boolean variable FOUND is initialized as false and assigned true or false based on whether:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A statement (but not expression) returns results with non-zero number of rows, or&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/control-flow/&#34;&gt;FOR&lt;/a&gt; loop iterates at least once&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can use FOUND to distinguish between a NULL and 0-row return.&lt;/p&gt;
&lt;p&gt;Special variables exist between the &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/scope-and-structure/&#34;&gt;scope&lt;/a&gt; of a procedure&#39;s argument and the outermost block of its definition. This means that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Special variables shadow procedure arguments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Variables declared in the body of the stored procedure will shadow the special variable&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following procedure demonstrates how FOUND changes. Before the SELECT statement, FOUND is false; after the SELECT statement, FOUND is true.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
BEGIN
    RAISE NOTICE &amp;#39;Before SELECT, FOUND = %&amp;#39;, FOUND;
    PERFORM SELECT 1; -- SELECT returns 1
    RAISE NOTICE &amp;#39;After SELECT, FOUND = %&amp;#39;, FOUND;
END;
$$;

NOTICE 2005:  Before SELECT, FOUND = f
NOTICE 2005:  After SELECT, FOUND = t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Similarly, UPDATE, DELETE, and INSERT return the number of rows affected. In the next example, UPDATE doesn&#39;t change any rows, but returns the value 0 to indicate that no rows were affected, so FOUND is set to true:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT * t1;
  a  |  b
-----+-----
 100 | abc
(1 row)

DO $$
BEGIN
    PERFORM UPDATE t1 SET a=200 WHERE b=&amp;#39;efg&amp;#39;; -- no rows affected since b doesn&amp;#39;t contain &amp;#39;efg&amp;#39;
    RAISE INFO &amp;#39;FOUND = %&amp;#39;, FOUND;
END;
$$;

INFO 2005:  FOUND = t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;FOUND starts as false and is set to true if the loop iterates at least once:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
BEGIN
    RAISE NOTICE &amp;#39;FOUND = %&amp;#39;, FOUND;
    FOR i IN RANGE 1..1 LOOP -- RANGE is inclusive, so iterates once
        RAISE NOTICE &amp;#39;i = %&amp;#39;, i;
    END LOOP;
    RAISE NOTICE &amp;#39;FOUND = %&amp;#39;, FOUND;
END;
$$;

NOTICE 2005:  FOUND = f
NOTICE 2005:  FOUND = t

DO $$
BEGIN
    RAISE NOTICE &amp;#39;FOUND = %&amp;#39;, FOUND;
    FOR i IN RANGE 1..0 LOOP
        RAISE NOTICE &amp;#39;i = %&amp;#39;, i;
    END LOOP;
    RAISE NOTICE &amp;#39;FOUND = %&amp;#39;, FOUND;
END;
$$;

NOTICE 2005:  FOUND = f
NOTICE 2005:  FOUND = f
&lt;/code&gt;&lt;/pre&gt;
      </description>
    </item>
    
    <item>
      <title>Extending: Control flow</title>
      <link>/en/extending/stored-procedures/plvsql/control-flow/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/extending/stored-procedures/plvsql/control-flow/</guid>
      <description>
        
        
        &lt;p&gt;Control flow constructs give you control over how many times and under what conditions a block of statements should run.&lt;/p&gt;
&lt;h2 id=&#34;conditionals&#34;&gt;Conditionals&lt;/h2&gt;
&lt;h3 id=&#34;ifelsifelse&#34;&gt;IF/ELSIF/ELSE&lt;/h3&gt;
&lt;p&gt;IF/ELSIF/ELSE statements let you perform different actions based on a specified condition.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;IF &lt;span class=&#34;code-variable&#34;&gt;condition_1&lt;/span&gt; THEN
  &lt;span class=&#34;code-variable&#34;&gt;statement_1&lt;/span&gt;;
[ ELSIF &lt;span class=&#34;code-variable&#34;&gt;condition_2&lt;/span&gt; THEN
  &lt;span class=&#34;code-variable&#34;&gt;statement_2&lt;/span&gt; ]
...
[ ELSE
  &lt;span class=&#34;code-variable&#34;&gt;statement_n&lt;/span&gt;; ]
END IF;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OpenText™ Analytics Database successively evaluates each condition as a boolean until it finds one that&#39;s true, then executes the block of statements and exits the IF statement. If no conditions are true, it executes the ELSE block, if one exists.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;
IF i = 3 THEN...
ELSIF 0 THEN...
ELSIF true THEN...
ELSIF x &amp;lt;= 4 OR x &amp;gt;= 10 THEN...
ELSIF y = &amp;#39;this&amp;#39; AND z = &amp;#39;THAT&amp;#39; THEN...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, this procedure demonstrates a simple IF...ELSE branch. Because &lt;code&gt;b&lt;/code&gt; is declared to be true, the database executes the first branch.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO LANGUAGE PLvSQL $$
DECLARE
    b bool := true;
BEGIN
    IF b THEN
        RAISE NOTICE &amp;#39;true branch&amp;#39;;
    ELSE
        RAISE NOTICE &amp;#39;false branch&amp;#39;;
    END IF;
END;
$$;

NOTICE 2005:  true branch
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;case&#34;&gt;CASE&lt;/h3&gt;
&lt;p&gt;CASE expressions are often more readable than IF...ELSE chains. After executing a CASE expression&#39;s branch, control jumps to the statement after the enclosing END CASE.&lt;/p&gt;
&lt;p&gt;PL/vSQL CASE expressions are more flexible and powerful than &lt;a href=&#34;../../../../en/sql-reference/language-elements/expressions/case-expressions/&#34;&gt;SQL case expressions&lt;/a&gt;, but the latter are more efficient; you should favor SQL case expressions when possible.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CASE [ &lt;span class=&#34;code-variable&#34;&gt;search_expression&lt;/span&gt; ]
   WHEN &lt;span class=&#34;code-variable&#34;&gt;expression_1&lt;/span&gt; [, &lt;span class=&#34;code-variable&#34;&gt;expression_2&lt;/span&gt;, ...] THEN
      &lt;span class=&#34;code-variable&#34;&gt;when_statements&lt;/span&gt;
  [ ... ]
  [ ELSE
      &lt;span class=&#34;code-variable&#34;&gt;else_statements&lt;/span&gt; ]
END CASE;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;&lt;code&gt;search_expression&lt;/code&gt;&lt;/em&gt; is evaluated once and then compared with &lt;em&gt;&lt;code&gt;expression_n&lt;/code&gt;&lt;/em&gt; in each branch from top to bottom. If &lt;em&gt;&lt;code&gt;search_expression&lt;/code&gt;&lt;/em&gt; and a given &lt;em&gt;&lt;code&gt;expression_n&lt;/code&gt;&lt;/em&gt; are equal, then the database executes the WHEN block for &lt;em&gt;&lt;code&gt;expression_n&lt;/code&gt;&lt;/em&gt; and exits the CASE block. If no matching expression is found, the ELSE branch is executed, if one exists.&lt;/p&gt;
&lt;p&gt;Case expressions must have either a matching case or an ELSE branch, otherwise the database displays a CASE_NOT_FOUND error.&lt;/p&gt;
&lt;p&gt;If you omit &lt;em&gt;&lt;code&gt;search_expression&lt;/code&gt;&lt;/em&gt;, its value defaults to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, this procedure plays the game FizzBuzz, printing Fizz if the argument is divisible by 3, Buzz if the argument is divisible by 5, FizzBuzz if the if the argument is divisible by 3 and 5.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; CREATE PROCEDURE fizzbuzz(IN x int) LANGUAGE PLvSQL AS $$
DECLARE
    fizz int := x % 3;
    buzz int := x % 5;
BEGIN
    CASE fizz
        WHEN 0 THEN -- if fizz = 0, execute WHEN block
            CASE buzz
                WHEN 0 THEN -- if buzz = 0, execute WHEN block
                    RAISE INFO &amp;#39;FizzBuzz&amp;#39;;
                ELSE -- if buzz != 0, execute WHEN block
                    RAISE INFO &amp;#39;Fizz&amp;#39;;
            END CASE;
        ELSE -- if fizz != 0, execute ELSE block
            CASE buzz
                WHEN 0 THEN
                    RAISE INFO &amp;#39;Buzz&amp;#39;;
                ELSE
                    RAISE INFO &amp;#39;&amp;#39;;
            END CASE;
    END CASE;
END;
$$;

=&amp;gt; CALL fizzbuzz(3);
INFO 2005:  Fizz

=&amp;gt; CALL fizzbuzz(5);
INFO 2005:  Buzz

=&amp;gt; CALL fizzbuzz(15);
INFO 2005:  FizzBuzz
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;loops&#34;&gt;Loops&lt;/h2&gt;
&lt;p&gt;Loops repeatedly execute a block of code until a given condition is satisfied.&lt;/p&gt;
&lt;h3 id=&#34;while&#34;&gt;WHILE&lt;/h3&gt;
&lt;p&gt;A WHILE loop checks a given condition and, if the condition is true, it executes the loop body, after which the condition is checked again: if true, the loop body executes again; if false, control jumps to the end of the loop body.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ &amp;lt;&amp;lt;&lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt;&amp;gt;&amp;gt; ]
WHILE &lt;span class=&#34;code-variable&#34;&gt;condition&lt;/span&gt; LOOP
   &lt;span class=&#34;code-variable&#34;&gt;statements&lt;/span&gt;;
END LOOP;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, this procedure computes the factorial of the argument:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; CREATE PROCEDURE factorialSP(input int) LANGUAGE PLvSQL AS $$
DECLARE
    i int := 1;
    output int := 1;
BEGIN
    WHILE i &amp;lt;= input loop
        output := output * i;
        i := i + 1;
    END LOOP;
    RAISE INFO &amp;#39;%! = %&amp;#39;, input, output;
END;
$$;

=&amp;gt; CALL factorialSP(5);
INFO 2005:  5! = 120
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;loop&#34;&gt;LOOP&lt;/h3&gt;
&lt;p&gt;This type of loop is equivalent to &lt;code&gt;WHILE true&lt;/code&gt; and only terminates if it encounters a RETURN or EXIT statement, or if an exception is thrown.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ &amp;lt;&amp;lt;label&amp;gt;&amp;gt; ]
LOOP
   &lt;span class=&#34;code-variable&#34;&gt;statements&lt;/span&gt;;
END LOOP;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, this procedure prints the integers from &lt;code&gt;counter&lt;/code&gt; up to &lt;code&gt;upper_bound&lt;/code&gt;, inclusive:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DO $$
DECLARE
    counter int := 1;
    upper_bound int := 3;
BEGIN
    LOOP
        RAISE INFO &amp;#39;%&amp;#39;, counter;
        IF counter &amp;gt;= upper_bound THEN
            RETURN;
        END IF;
        counter := counter + 1;
    END LOOP;
END;
$$;

INFO 2005:  1
INFO 2005:  2
INFO 2005:  3
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;for&#34;&gt;FOR&lt;/h3&gt;
&lt;p&gt;FOR loops iterate over a collection, which can be an integral range, query, or cursor.&lt;/p&gt;
&lt;p&gt;If a FOR loop iterates at least once, the special &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/embedded-sql/#found&#34;&gt;FOUND variable&lt;/a&gt; is set to true after the loop ends. Otherwise, FOUND is set to false.&lt;/p&gt;
&lt;p&gt;The FOUND variable can be useful for distinguishing between a NULL and 0-row return, or creating an IF branch if a LOOP didn&#39;t run.&lt;/p&gt;
&lt;h4 id=&#34;for-range&#34;&gt;FOR (RANGE)&lt;/h4&gt;
&lt;p&gt;A FOR (RANGE) loop iterates over a range of integers specified by the expressions &lt;em&gt;&lt;code&gt;left&lt;/code&gt;&lt;/em&gt; and &lt;em&gt;&lt;code&gt;right&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ &amp;lt;&amp;lt;label&amp;gt;&amp;gt; ]
FOR &lt;span class=&#34;code-variable&#34;&gt;loop_counter&lt;/span&gt; IN RANGE [ REVERSE ] &lt;span class=&#34;code-variable&#34;&gt;left&lt;/span&gt;..&lt;span class=&#34;code-variable&#34;&gt;right&lt;/span&gt; [ BY &lt;span class=&#34;code-variable&#34;&gt;step&lt;/span&gt; ] LOOP
    &lt;span class=&#34;code-variable&#34;&gt;statements&lt;/span&gt;
END LOOP [ &lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;&lt;code&gt;loop_counter&lt;/code&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;does not have to be declared and is initialized with the value of &lt;em&gt;&lt;code&gt;left&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;is only available within the scope of the FOR loop&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;loop_counter&lt;/code&gt;&lt;/em&gt; iterates from &lt;em&gt;&lt;code&gt;left&lt;/code&gt;&lt;/em&gt; to &lt;em&gt;&lt;code&gt;right&lt;/code&gt;&lt;/em&gt; (inclusive), incrementing by &lt;em&gt;&lt;code&gt;step&lt;/code&gt;&lt;/em&gt; at the end of each iteration.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;REVERSE&lt;/code&gt; option instead iterates from &lt;em&gt;&lt;code&gt;right&lt;/code&gt;&lt;/em&gt; to &lt;em&gt;&lt;code&gt;left&lt;/code&gt;&lt;/em&gt; (inclusive), decrementing by &lt;em&gt;&lt;code&gt;step&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example, here is a standard ascending FOR loop with &lt;em&gt;&lt;code&gt;step&lt;/code&gt;&lt;/em&gt; = 1:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
BEGIN
    FOR i IN RANGE 1..4 LOOP -- loop_counter i does not have to be declared
        RAISE NOTICE &amp;#39;i = %&amp;#39;, i;
    END LOOP;
    RAISE NOTICE &amp;#39;after loop: i = %&amp;#39;, i; -- fails
END;
$$;

NOTICE 2005:  i = 1
NOTICE 2005:  i = 2
NOTICE 2005:  i = 3
NOTICE 2005:  i = 4
ERROR 2624:  Column &amp;#34;i&amp;#34; does not exist -- loop_counter i is only available inside the FOR loop
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here, the &lt;em&gt;&lt;code&gt;loop_counter&lt;/code&gt;&lt;/em&gt; &lt;code&gt;i&lt;/code&gt; starts at 4 and decrements by 2 at the end of each iteration:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
BEGIN
    FOR i IN RANGE REVERSE 4..0 BY 2 LOOP
        RAISE NOTICE &amp;#39;i = %&amp;#39;, i;
    END LOOP;
END;
$$;

NOTICE 2005:  i = 4
NOTICE 2005:  i = 2
NOTICE 2005:  i = 0
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;for-query&#34;&gt;FOR (query)&lt;/h4&gt;
&lt;p&gt;A FOR (QUERY) loop iterates over the results of a query.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ &amp;lt;&amp;lt;label&amp;gt;&amp;gt; ]
FOR &lt;span class=&#34;code-variable&#34;&gt;target&lt;/span&gt; IN QUERY &lt;span class=&#34;code-variable&#34;&gt;statement&lt;/span&gt; LOOP
    &lt;span class=&#34;code-variable&#34;&gt;statements&lt;/span&gt;
END LOOP [ &lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can include an &lt;a href=&#34;../../../../en/sql-reference/statements/select/order-by-clause/&#34;&gt;ORDER BY clause&lt;/a&gt; in the query to make the ordering deterministic.&lt;/p&gt;
&lt;p&gt;Unlike FOR (RANGE) loops, you must declare the &lt;em&gt;&lt;code&gt;target&lt;/code&gt;&lt;/em&gt; variables. The values of these variables persist after the loop ends.&lt;/p&gt;
&lt;p&gt;For example, suppose given the table &lt;code&gt;tuple&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT * FROM tuples ORDER BY x ASC;
 x | y | z
---+---+---
 1 | 2 | 3
 4 | 5 | 6
 7 | 8 | 9
(3 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This procedure retrieves the tuples in each row and stores them in the variables &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt;, and prints them after each iteration:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt;
=&amp;gt; DO $$
DECLARE
    a int; -- target variables must be declared
    b int;
    c int;
    i int := 1;
BEGIN
    FOR a,b,c IN QUERY SELECT * FROM tuples ORDER BY x ASC LOOP
        RAISE NOTICE &amp;#39;iteration %: a = %, b = %, c = %&amp;#39;, i,a,b,c;
        i := i + 1;
    END LOOP;
    RAISE NOTICE &amp;#39;after loop: a = %, b = %, c = %&amp;#39;, a,b,c;
END;
$$;

NOTICE 2005:  iteration 1: a = 1, b = 2, c = 3
NOTICE 2005:  iteration 2: a = 4, b = 5, c = 6
NOTICE 2005:  iteration 3: a = 7, b = 8, c = 9
NOTICE 2005:  after loop: a = 7, b = 8, c = 9
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can also use a query constructed dynamically with &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/embedded-sql/&#34;&gt;EXECUTE&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ &amp;lt;&amp;lt;label&amp;gt;&amp;gt; ]
FOR &lt;span class=&#34;code-variable&#34;&gt;target&lt;/span&gt; IN EXECUTE &amp;#39;&lt;span class=&#34;code-variable&#34;&gt;statement&lt;/span&gt;&amp;#39; [ USING &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt; [, ... ] ] LOOP
    &lt;span class=&#34;code-variable&#34;&gt;statements&lt;/span&gt;
END LOOP [ &lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following procedure uses EXECUTE to construct a FOR (QUERY) loop and stores the results of that SELECT statement in the variables &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. The result set of a statement like this has only one row, so it only iterates once.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT &amp;#39;first string&amp;#39;, &amp;#39;second string&amp;#39;;
   ?column?   |   ?column?
--------------+---------------
 first string | second string
(1 row)

=&amp;gt; DO $$
DECLARE
    x varchar; -- target variables must be declared
    y varchar;
BEGIN
    -- substitute the placeholders $1 and $2 with the strings
    FOR x, y IN EXECUTE &amp;#39;SELECT $1, $2&amp;#39; USING &amp;#39;first string&amp;#39;, &amp;#39;second string&amp;#39; LOOP
        RAISE NOTICE &amp;#39;%&amp;#39;, x;
        RAISE NOTICE &amp;#39;%&amp;#39;, y;
    END LOOP;
END;
$$;

NOTICE 2005:  first string
NOTICE 2005:  second string
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;for-cursor&#34;&gt;FOR (cursor)&lt;/h4&gt;
&lt;p&gt;A FOR (CURSOR) loop iterates over a &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/cursors/&#34;&gt;bound, unopened cursor&lt;/a&gt;, executing some set of &lt;em&gt;&lt;code&gt;statements&lt;/code&gt;&lt;/em&gt; for each iteration.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ &amp;lt;&amp;lt;label&amp;gt;&amp;gt; ]
FOR &lt;span class=&#34;code-variable&#34;&gt;loop_variable&lt;/span&gt; [, ...] IN CURSOR &lt;span class=&#34;code-variable&#34;&gt;bound_unopened_cursor&lt;/span&gt; [ ( [ &lt;span class=&#34;code-variable&#34;&gt;arg_name&lt;/span&gt; := ] &lt;span class=&#34;code-variable&#34;&gt;arg_value&lt;/span&gt; [, ...] ) ] LOOP
    &lt;span class=&#34;code-variable&#34;&gt;statements&lt;/span&gt;
END LOOP [ &lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This type of FOR loop opens the cursor at start of the loop and closes at the end.&lt;/p&gt;
&lt;p&gt;For example, this procedure creates a cursor &lt;code&gt;c&lt;/code&gt;. The procedure passes &lt;code&gt;6&lt;/code&gt; as an argument to the cursor, so the cursor only retrieves rows where the y-coordinate is 6, storing the coordinates in the variables &lt;code&gt;x_&lt;/code&gt;, &lt;code&gt;y_&lt;/code&gt;, and &lt;code&gt;z_&lt;/code&gt; and printing them at the end of each iteration:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT * FROM coordinates;
 x  | y | z
----+---+----
 14 | 6 | 19
  1 | 6 |  2
 10 | 6 | 39
 10 | 2 | 1
  7 | 1 | 10
 67 | 1 | 77
(6 rows)

DO $$
DECLARE
    c CURSOR (key int) FOR SELECT * FROM coordinates WHERE y=key;
    x_ int;
    y_ int;
    z_ int;
BEGIN
    FOR x_,y_,z_ IN CURSOR c(6) LOOP
       RAISE NOTICE &amp;#39;cursor returned %,%,% FOUND=%&amp;#39;, x_,y_,z_,FOUND;
    END LOOP;
    RAISE NOTICE &amp;#39;after loop: %,%,% FOUND=%&amp;#39;, x_,y_,z_,FOUND;
END;
$$;

NOTICE 2005:  cursor returned 14,6,19 FOUND=f -- FOUND is only set after the loop ends
NOTICE 2005:  cursor returned 1,6,2 FOUND=f
NOTICE 2005:  after loop: 10,6,39 FOUND=t -- x_, y_, and z_ retain their values, FOUND is now true because the FOR loop iterated at least once
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;manipulating-loops&#34;&gt;Manipulating loops&lt;/h3&gt;
&lt;h4 id=&#34;return&#34;&gt;RETURN&lt;/h4&gt;
&lt;p&gt;You can exit the entire procedure (and therefore the loop) with RETURN. RETURN is an optional statement and can be added to signal to readers the end of a procedure.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;RETURN;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;exit&#34;&gt;EXIT&lt;/h4&gt;
&lt;p&gt;Similar to a &lt;code&gt;break&lt;/code&gt; or labeled &lt;code&gt;break&lt;/code&gt; in other programming languages, EXIT statements let you exit a loop early, optionally specifying:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;loop_label&lt;/code&gt;&lt;/em&gt;: the name of the loop to exit from&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;condition&lt;/code&gt;&lt;/em&gt;: if the &lt;em&gt;&lt;code&gt;condition&lt;/code&gt;&lt;/em&gt; is &lt;code&gt;true&lt;/code&gt;, execute the EXIT statement&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;EXIT [ &lt;span class=&#34;code-variable&#34;&gt;loop_label&lt;/span&gt; ] [ WHEN &lt;span class=&#34;code-variable&#34;&gt;condition&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;continue&#34;&gt;CONTINUE&lt;/h4&gt;
&lt;p&gt;CONTINUE skips to the next iteration of the loop without executing statements that follow the CONTINUE itself. You can specify a particular loop with &lt;em&gt;&lt;code&gt;loop_label&lt;/code&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CONTINUE [&lt;span class=&#34;code-variable&#34;&gt;loop_label&lt;/span&gt;] [ WHEN &lt;span class=&#34;code-variable&#34;&gt;condition&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, this procedure doesn&#39;t print during its first two iterations because the CONTINUE statement executes and moves on to the next iteration of the loop before control reaches the RAISE NOTICE statement:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
BEGIN
    FOR i IN RANGE 1..5 LOOP
        IF i &amp;lt; 3 THEN
            CONTINUE;
        END IF;
        RAISE NOTICE &amp;#39;i = %&amp;#39;, i;
    END LOOP;
END;
$$;

NOTICE 2005:  i = 3
NOTICE 2005:  i = 4
NOTICE 2005:  i = 5
&lt;/code&gt;&lt;/pre&gt;
      </description>
    </item>
    
    <item>
      <title>Extending: Errors and diagnostics</title>
      <link>/en/extending/stored-procedures/plvsql/errors-and-diagnostics/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/extending/stored-procedures/plvsql/errors-and-diagnostics/</guid>
      <description>
        
        
        &lt;h2 id=&#34;assert&#34;&gt;ASSERT&lt;/h2&gt;
&lt;p&gt;ASSERT is a debugging feature that checks whether a condition is &lt;code&gt;true&lt;/code&gt;. If the condition is &lt;code&gt;false&lt;/code&gt;, ASSERT raises an &lt;code&gt;ASSERT_FAILURE&lt;/code&gt; exception with an optional error message.&lt;/p&gt;
&lt;p&gt;To escape a &lt;code&gt;&#39;&lt;/code&gt; (single quote) character, use &lt;code&gt;&#39;&#39;&lt;/code&gt;. Similarly, to escape a &lt;code&gt;&amp;quot;&lt;/code&gt; (double quote) character, use &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;.&lt;/p&gt;

&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ASSERT &lt;span class=&#34;code-variable&#34;&gt;condition&lt;/span&gt; [ , &lt;span class=&#34;code-variable&#34;&gt;message&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, this procedure checks the number of rows in the &lt;code&gt;products&lt;/code&gt; table and uses ASSERT to check that the table is populated. If the table is empty, OpenText™ Analytics Database raises an error:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;
=&amp;gt; CREATE TABLE products(id UUID, name VARCHARE, price MONEY);
CREATE TABLE

=&amp;gt; SELECT * FROM products;
 id | name | price
----+------+-------
(0 rows)

DO $$
DECLARE
    prod_count INT;
BEGIN
    prod_count := SELECT count(*) FROM products;
    ASSERT prod_count &amp;gt; 0, &amp;#39;products table is empty&amp;#39;;
END;
$$;

ERROR 2005:  products table is empty
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To stop the database from checking ASSERT statements, &lt;a href=&#34;../../../../en/sql-reference/statements/alter-statements/alter-session/&#34;&gt;you can set the boolean session-level parameter&lt;/a&gt; &lt;code&gt;PLpgSQLCheckAsserts&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;raise&#34;&gt;RAISE&lt;/h2&gt;
&lt;p&gt;RAISE can display errors or print a user-specified error message, one of the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;RAISE [ &lt;span class=&#34;code-variable&#34;&gt;level&lt;/span&gt; ] &amp;#39;&lt;span class=&#34;code-variable&#34;&gt;format&lt;/span&gt;&amp;#39; [, &lt;span class=&#34;code-variable&#34;&gt;arg_expression&lt;/span&gt; [, ... ]] [ USING option = &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt; [, ... ] ];
RAISE [ &lt;span class=&#34;code-variable&#34;&gt;level&lt;/span&gt; ] condition_name [ USING option = &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt; [, ... ] ];
RAISE [ &lt;span class=&#34;code-variable&#34;&gt;level&lt;/span&gt; ] SQLSTATE &amp;#39;&lt;span class=&#34;code-variable&#34;&gt;sql-state&lt;/span&gt;&amp;#39; [ USING option = &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt; [, ... ] ];
RAISE [ &lt;span class=&#34;code-variable&#34;&gt;level&lt;/span&gt; ] USING &lt;span class=&#34;code-variable&#34;&gt;option&lt;/span&gt; = &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt; [, ... ];
&lt;/code&gt;&lt;/pre&gt;
&lt;table class=&#34;table table-bordered&#34; &gt;



&lt;tr&gt; 

&lt;td &gt;
&lt;em&gt;&lt;code&gt;level&lt;/code&gt;&lt;/em&gt;&lt;/td&gt; 

&lt;td &gt;











&lt;p&gt;VARCHAR, one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;LOG: Sends the &lt;em&gt;&lt;code&gt;format&lt;/code&gt;&lt;/em&gt; to &lt;code&gt;vertica.log&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;INFO: Prints an INFO message in VSQL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NOTICE: Prints a NOTICE in VSQL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;WARNING: Prints a WARNING in VSQL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;EXCEPTION: Throws catchable exception&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Default:&lt;/strong&gt; EXCEPTION&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;em&gt;&lt;code&gt;format&lt;/code&gt;&lt;/em&gt;&lt;/td&gt; 

&lt;td &gt;







&lt;p&gt;VARCHAR, a string literal error message where the percent character &lt;code&gt;%&lt;/code&gt; is substituted with the *&lt;code&gt;arg_expression&lt;/code&gt;*s. &lt;code&gt;%%&lt;/code&gt; escapes the substitution and results in a single &lt;code&gt;%&lt;/code&gt; in plaintext.&lt;/p&gt;
&lt;p&gt;If the number of &lt;code&gt;%&lt;/code&gt; characters doesn&#39;t equal the number of arguments, the database displays an error.&lt;/p&gt;
&lt;p&gt;To escape a &lt;code&gt;&#39;&lt;/code&gt; (single quote) character, use &lt;code&gt;&#39;&#39;&lt;/code&gt;. Similarly, to escape a &lt;code&gt;&amp;quot;&lt;/code&gt; (double quote) character, use &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;em&gt;&lt;code&gt;arg_expression&lt;/code&gt;&lt;/em&gt;&lt;/td&gt; 

&lt;td &gt;


An expression that substitutes for the percent character (&lt;code&gt;%&lt;/code&gt;) in the &lt;em&gt;&lt;code&gt;format&lt;/code&gt;&lt;/em&gt; string.&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;em&gt;&lt;code&gt;option&lt;/code&gt;&lt;/em&gt; = &lt;em&gt;&lt;code&gt;expression&lt;/code&gt;&lt;/em&gt;&lt;/td&gt; 

&lt;td &gt;















































































































&lt;p&gt;&lt;em&gt;&lt;code&gt;option&lt;/code&gt;&lt;/em&gt; must be one of the following and paired with an &lt;em&gt;&lt;code&gt;expression&lt;/code&gt;&lt;/em&gt; that elaborates on the &lt;em&gt;&lt;code&gt;option&lt;/code&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;table class=&#34;table table-bordered&#34; &gt;
&lt;tr&gt; 
&lt;th &gt;
&lt;em&gt;option&lt;/em&gt;&lt;/th&gt; 
&lt;th &gt;
&lt;em&gt;expression&lt;/em&gt; content&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
MESSAGE&lt;/td&gt; 
&lt;td &gt;
&lt;p&gt;An error message.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Default:&lt;/strong&gt; the ERRCODE associated with the exception&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
DETAIL&lt;/td&gt; 
&lt;td &gt;
Details about the error.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
HINT&lt;/td&gt; 
&lt;td &gt;
A hint message.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
ERRCODE&lt;/td&gt; 
&lt;td &gt;
&lt;p&gt;The error code to report, one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A condition name specified in the &lt;code&gt;description&lt;/code&gt; column of the &lt;a href=&#34;../../../../en/error-messages/sql-state-list/#&#34;&gt;SQL state list&lt;/a&gt; (with optional &lt;code&gt;ERRCODE_&lt;/code&gt; prefix)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A code that satisfies the SQLSTATE formatting: 5-character sequence of numbers and capital letters (not necessarily on the SQL State List)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Default:&lt;/strong&gt; ERRCODE_RAISE_EXCEPTION (V0002)&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
COLUMN&lt;/td&gt; 
&lt;td &gt;
A column name relevant to the error&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
CONSTRAINT&lt;/td&gt; 
&lt;td &gt;
A constraint relevant to the error&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
DATATYPE&lt;/td&gt; 
&lt;td &gt;
A data type relevant to the error&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
TABLE&lt;/td&gt; 
&lt;td &gt;
A table name relevant to the error&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt; 
&lt;td &gt;
SCHEMA&lt;/td&gt; 
&lt;td &gt;
A schema name relevant to the error&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This procedure demonstrates various RAISE levels:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
DECLARE
    logfile varchar := &amp;#39;vertica.log&amp;#39;;
BEGIN
    RAISE LOG &amp;#39;this message was sent to %&amp;#39;, logfile;
    RAISE INFO &amp;#39;info&amp;#39;;
    RAISE NOTICE &amp;#39;notice&amp;#39;;
    RAISE WARNING &amp;#39;warning&amp;#39;;
    RAISE EXCEPTION &amp;#39;exception&amp;#39;;

    RAISE NOTICE &amp;#39;exception changes control flow; this is not printed&amp;#39;;
END;
$$;

INFO 2005:  info
NOTICE 2005:  notice
WARNING 2005:  warning
ERROR 2005:  exception

$ grep &amp;#39;this message was sent to vertica.log&amp;#39; v_vmart_node0001_catalog/vertica.log
&amp;lt;LOG&amp;gt; @v_vmart_node0001: V0002/2005: this message is sent to vertica.log
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;exceptions&#34;&gt;Exceptions&lt;/h2&gt;
&lt;p&gt;EXCEPTION blocks let you catch and handle &lt;a href=&#34;../../../../en/error-messages/sql-state-list/&#34;&gt;exceptions&lt;/a&gt; that might get thrown from &lt;em&gt;&lt;code&gt;statements&lt;/code&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ &amp;lt;&amp;lt;&lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt;&amp;gt;&amp;gt; ]
[ DECLARE
    &lt;span class=&#34;code-variable&#34;&gt;declarations&lt;/span&gt; ]
BEGIN
    &lt;span class=&#34;code-variable&#34;&gt;statements&lt;/span&gt;
EXCEPTION
    WHEN &lt;span class=&#34;code-variable&#34;&gt;exception_condition&lt;/span&gt; [ OR &lt;span class=&#34;code-variable&#34;&gt;exception_condition&lt;/span&gt; ... ] THEN
        &lt;span class=&#34;code-variable&#34;&gt;handler_statements&lt;/span&gt;
    [ WHEN &lt;span class=&#34;code-variable&#34;&gt;exception_condition&lt;/span&gt; [ OR &lt;span class=&#34;code-variable&#34;&gt;exception_condition&lt;/span&gt; ... ] THEN
        &lt;span class=&#34;code-variable&#34;&gt;handler_statements&lt;/span&gt;
      ... ]
END [ &lt;span class=&#34;code-variable&#34;&gt;label&lt;/span&gt; ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;&lt;code&gt;exception_condition&lt;/code&gt;&lt;/em&gt; has one of the following forms:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;WHEN &lt;span class=&#34;code-input&#34;&gt;errcode_division_by_zero&lt;/span&gt; THEN ...
WHEN &lt;span class=&#34;code-input&#34;&gt;division_by_zero&lt;/span&gt; THEN ...
WHEN &lt;span class=&#34;code-input&#34;&gt;SQLSTATE &#39;22012&#39;&lt;/span&gt; THEN ...
WHEN OTHERS THEN ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OTHERS is a special condition that catches all exceptions except &lt;code&gt;QUERY_CANCELLED&lt;/code&gt;, &lt;code&gt;ASSERT_FAILURE&lt;/code&gt;, and &lt;code&gt;FEATURE_NOT_SUPPORTED&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When an exception is thrown, the database checks the list of exceptions for a matching &lt;em&gt;&lt;code&gt;exception_condition&lt;/code&gt;&lt;/em&gt; from top to bottom. If it finds a match, it executes the &lt;em&gt;&lt;code&gt;handler_statements&lt;/code&gt;&lt;/em&gt; and then leaves the exception block&#39;s scope.&lt;/p&gt;
&lt;p&gt;If the database can&#39;t find a match, it propagates the exception up to the next enclosing block. You can do this manually within an exception handler with RAISE:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;RAISE;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, the following procedure divides 3 by 0 in the &lt;code&gt;inner_block&lt;/code&gt;, which is an illegal operation that throws the exception &lt;code&gt;division_by_zero&lt;/code&gt; with SQL state 22012. The database checks the inner EXCEPTION block for a matching condition:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The first condition checks for SQL state 42501, so the database moves to the next condition.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;WHEN OTHERS THEN catches all exceptions, it executes that block.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The bare RAISE then propagates the exception to the &lt;code&gt;outer_block&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The outer EXCEPTION block successfully catches the exception and prints a message.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
&amp;lt;&amp;lt;outer_block&amp;gt;&amp;gt;
BEGIN
    &amp;lt;&amp;lt;inner_block&amp;gt;&amp;gt;
    DECLARE
        x int;
    BEGIN
        x := 3 / 0; -- throws exception division_by_zero, SQLSTATE 22012
    EXCEPTION -- this block is checked first for matching exceptions
        WHEN SQLSTATE &amp;#39;42501&amp;#39; THEN
            RAISE NOTICE &amp;#39;caught insufficient_privilege exception&amp;#39;;
        WHEN OTHERS THEN -- catches all exceptions
            RAISE; -- manually propagate the exception to the next enclosing block
    END inner_block;
EXCEPTION -- exception is propagated to this block
    WHEN division_by_zero THEN
        RAISE NOTICE &amp;#39;caught division_by_zero exception&amp;#39;;
END outer_block;
$$;

NOTICE 2005:  caught division_by_zero exception
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;sqlstate-and-sqlerrm-variables&#34;&gt;SQLSTATE and SQLERRM variables&lt;/h3&gt;
&lt;p&gt;When handling an exception, you can use the following variables to retrieve error information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SQLSTATE&lt;/code&gt; contains the SQL state&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SQLERRM&lt;/code&gt; contains the error message&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For details, see &lt;a href=&#34;../../../../en/error-messages/sql-state-list/#&#34;&gt;SQL state list&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This procedure catches the exception thrown by attempting to assign NULL to a NOT NULL variable and prints the SQL state and error message:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DO $$
DECLARE
    i int NOT NULL := 1;
BEGIN
    i := NULL; -- illegal, i was declared with NOT NULL
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING &amp;#39;SQL State: %&amp;#39;, SQLSTATE;
        RAISE WARNING &amp;#39;Error message: %&amp;#39;, SQLERRM;
END;
$$;

WARNING 2005:  SQLSTATE: 42809
WARNING 2005:  SQLERRM: Cannot assign null into NOT NULL variable
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;retrieving-exception-information&#34;&gt;Retrieving exception information&lt;/h2&gt;
&lt;p&gt;You can retrieve information about exceptions inside exception handlers with GET STACKED DIAGNOSTICS:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;GET STACKED DIAGNOSTICS &lt;span class=&#34;code-variable&#34;&gt;variable_name&lt;/span&gt; { = | := } &lt;span class=&#34;code-variable&#34;&gt;item&lt;/span&gt; [, ... ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Where &lt;em&gt;&lt;code&gt;item&lt;/code&gt;&lt;/em&gt; can be any of the following:

&lt;table class=&#34;table table-bordered&#34; &gt;



&lt;tr&gt; 

&lt;th &gt;
&lt;em&gt;item&lt;/em&gt;&lt;/th&gt; 

&lt;th &gt;
Description&lt;/th&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;RETURNED_SQLSTATE&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
SQLSTATE error code of the exception&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;COLUMN_NAME&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Name of the column related to exception&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;CONSTRAINT_NAME&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Name of the constraint related to exception&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;DATATYPE_NAME&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Name of the data type related to exception&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;MESSAGE_TEXT&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Text of the exception&#39;s primary message&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;TABLE_NAME&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Name of the table related to exception&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;SCHEMA_NAME&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Name of the schema related to exception&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;DETAIL_TEXT&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Text of the exception&#39;s detail message, if any&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;HINT_TEXT&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Text of the exception&#39;s hint message, if any&lt;/td&gt;&lt;/tr&gt;

&lt;tr&gt; 

&lt;td &gt;
&lt;code&gt;EXCEPTION_CONTEXT&lt;/code&gt;&lt;/td&gt; 

&lt;td &gt;
Description of the call stack at the time of the exception&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;For example, this procedure has an EXCEPTION block that catches the &lt;code&gt;division_by_zero&lt;/code&gt; error and prints SQL state, error message, and the exception context:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; DO $$
DECLARE
    message_1 varchar;
    message_2 varchar;
    message_3 varchar;
    x int;
BEGIN
    x := 5 / 0;
EXCEPTION
    WHEN OTHERS THEN -- OTHERS catches all exceptions
    GET STACKED DIAGNOSTICS message_1 = RETURNED_SQLSTATE,
                            message_2 = MESSAGE_TEXT,
                            message_3 = EXCEPTION_CONTEXT;

    RAISE INFO &amp;#39;SQLSTATE: %&amp;#39;, message_1;
    RAISE INFO &amp;#39;MESSAGE: %&amp;#39;, message_2;
    RAISE INFO &amp;#39;EXCEPTION_CONTEXT: %&amp;#39;, message_3;
END;
$$;

INFO 2005:  SQLSTATE: 22012
INFO 2005:  MESSAGE: Division by zero
INFO 2005:  EXCEPTION_CONTEXT: PL/vSQL procedure inline_code_block line 8 at static SQL
&lt;/code&gt;&lt;/pre&gt;
      </description>
    </item>
    
    <item>
      <title>Extending: Cursors</title>
      <link>/en/extending/stored-procedures/plvsql/cursors/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/extending/stored-procedures/plvsql/cursors/</guid>
      <description>
        
        
        &lt;p&gt;A cursor is a reference to the result set of a query and allows you to view the results one row at a time. Cursors remember their positions in result sets, which can be one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;a result row&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;before the first row&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;after the last row&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also iterate over unopened, bound cursors with a FOR loop. See &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/control-flow/#forcursor&#34;&gt;Control Flow&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h2 id=&#34;declaring-cursors&#34;&gt;Declaring cursors&lt;/h2&gt;
&lt;h3 id=&#34;bound-cursors&#34;&gt;Bound cursors&lt;/h3&gt;
&lt;p&gt;To bind a cursor to a &lt;em&gt;&lt;code&gt;statement&lt;/code&gt;&lt;/em&gt; on declaration, use the FOR keyword:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;cursor_name&lt;/span&gt; CURSOR [ ( &lt;span class=&#34;code-variable&#34;&gt;arg_name&lt;/span&gt; &lt;span class=&#34;code-variable&#34;&gt;arg_type&lt;/span&gt; [, ...] ) ] FOR &lt;span class=&#34;code-variable&#34;&gt;statement&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The arguments to a cursor give you more control over which rows to process. For example, suppose you have the following table:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT * FROM coordinates_xy;
 x | y
---+----
 1 |  2
 9 |  5
 7 | 13
...
(100000 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you&#39;re only interested in the rows where &lt;code&gt;y&lt;/code&gt; is 6, you might declare the following cursor and then provide the argument &lt;code&gt;6&lt;/code&gt; when you &lt;a href=&#34;#open&#34;&gt;OPEN&lt;/a&gt; the cursor:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;c CURSOR (key int) FOR SELECT * FROM coordinates_xy WHERE y=key;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;unbound-cursors&#34;&gt;Unbound cursors&lt;/h3&gt;
&lt;p&gt;To declare a cursor without binding it to a particular query, use the &lt;code&gt;refcursor&lt;/code&gt; type:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;cursor_name&lt;/span&gt; refcursor;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can bind an unbound cursor at any time with &lt;a href=&#34;#open&#34;&gt;OPEN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example, to declare the cursor &lt;code&gt;my_unbound_cursor&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;my_unbound_cursor refcursor;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;opening-and-closing-cursors&#34;&gt;Opening and closing cursors&lt;/h2&gt;
&lt;h3 id=&#34;open&#34;&gt;OPEN&lt;/h3&gt;
&lt;p&gt;Opening a cursor executes the query with the given arguments, and puts the cursor before the first row of the result set. The ordering of query results (and therefore, the start of the result set) is non-deterministic, unless you specify an &lt;a href=&#34;../../../../en/sql-reference/statements/select/order-by-clause/&#34;&gt;ORDER BY clause&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;open-a-bound-cursor&#34;&gt;OPEN a bound cursor&lt;/h4&gt;
&lt;p&gt;To open a cursor that was bound during declaration:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;OPEN &lt;span class=&#34;code-variable&#34;&gt;bound_cursor&lt;/span&gt; [ ( [ &lt;span class=&#34;code-variable&#34;&gt;arg_name&lt;/span&gt; := ] &lt;span class=&#34;code-variable&#34;&gt;arg_value&lt;/span&gt; [, ...] ) ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, given the following declaration:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;c CURSOR (key int) FOR SELECT * FROM t1 WHERE y=key;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can open the cursor with one of the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;OPEN c(5);
OPEN c(key := 5);
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;close&#34;&gt;CLOSE&lt;/h3&gt;
&lt;p&gt;Open cursors are automatically closed when the cursor leaves scope, but you can close the cursor preemptively with CLOSE. Closed cursors can be reopened later, which re-executes the query and prepares a new result set.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CLOSE &lt;span class=&#34;code-variable&#34;&gt;cursor&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;open-an-unbound-cursor&#34;&gt;OPEN an unbound cursor&lt;/h4&gt;
&lt;p&gt;To bind an unbound cursor and then open it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;OPEN &lt;span class=&#34;code-variable&#34;&gt;unbound_cursor&lt;/span&gt; FOR &lt;span class=&#34;code-variable&#34;&gt;statement&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can also use &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/embedded-sql/&#34;&gt;EXECUTE&lt;/a&gt; because it&#39;s a statement:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;OPEN &lt;span class=&#34;code-variable&#34;&gt;unbound_cursor&lt;/span&gt; FOR EXECUTE &lt;span class=&#34;code-variable&#34;&gt;statement_string&lt;/span&gt; [ USING &lt;span class=&#34;code-variable&#34;&gt;expression&lt;/span&gt; [, ... ] ];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, to bind the cursor &lt;code&gt;c&lt;/code&gt; to a query to a table &lt;code&gt;product_data&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;OPEN c for SELECT * FROM product_data;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;fetch-rows&#34;&gt;FETCH rows&lt;/h2&gt;
&lt;p&gt;FETCH statements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Retrieve the row that the specified cursor currently points to and stores it in some variable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Advance the cursor to the next position.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;span class=&#34;code-variable&#34;&gt;variable&lt;/span&gt; [, ...] := FETCH &lt;span class=&#34;code-variable&#34;&gt;opened_cursor&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The retrieved value is stored in &lt;em&gt;&lt;code&gt;variable&lt;/code&gt;&lt;/em&gt;. Rows typically have more than one value, so you can use one variable for each.&lt;/p&gt;
&lt;p&gt;If FETCH successfully retrieves a value, the special variable &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/embedded-sql/#found&#34;&gt;FOUND&lt;/a&gt; is set to &lt;code&gt;true&lt;/code&gt;. Otherwise, if you call FETCH when the cursor is past the final row of the result set, it returns NULL and the special variable FOUND is set to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The following procedure creates a cursor &lt;code&gt;c&lt;/code&gt;, binding it to a SELECT query on the &lt;code&gt;coordinates&lt;/code&gt; table. The procedures passes the argument 1 to the cursor, so the cursor only retrieves rows where the y-coordinate is 1, storing the coordinates in the variables &lt;code&gt;x_&lt;/code&gt;, &lt;code&gt;y_&lt;/code&gt;, and &lt;code&gt;z_&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Only two rows have a y-coordinate of 1, so after using FETCH twice, the third FETCH starts to return NULL values and FOUND is set to &lt;code&gt;false&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT * FROM coordinates;
 x  | y | z
----+---+----
 14 | 6 | 19
  1 | 6 |  2
 10 | 6 | 39
 10 | 2 |  1
  7 | 1 | 10
 67 | 1 | 77
(6 rows)

DO $$
DECLARE
    c CURSOR (key int) FOR SELECT * FROM coordinates WHERE y=key;
    x_ int;
    y_ int;
    z_ int;
BEGIN
    OPEN c(1); -- only retrieve rows where y=1
    x_,y_,z_ := FETCH c;
    RAISE NOTICE &amp;#39;cursor returned %, %, %, FOUND=%&amp;#39;,x_, y_, z_, FOUND;
    x_,y_,z_ := FETCH c; -- fetches the last set of results and moves to the end of the result set
    RAISE NOTICE &amp;#39;cursor returned %, %, %, FOUND=%&amp;#39;,x_, y_, z_, FOUND;
    x_,y_,z_ := FETCH c; -- cursor has advanced past the final row
    RAISE NOTICE &amp;#39;cursor returned %, %, %, FOUND=%&amp;#39;,x_, y_, z_, FOUND;
END;
$$;

NOTICE 2005:  cursor returned 7, 1, 10, FOUND=t
NOTICE 2005:  cursor returned 67, 1, 77, FOUND=t
NOTICE 2005:  cursor returned &amp;lt;NULL&amp;gt;, &amp;lt;NULL&amp;gt;, &amp;lt;NULL&amp;gt;, FOUND=f
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;move-cursors&#34;&gt;MOVE cursors&lt;/h2&gt;
&lt;p&gt;MOVE advances an &lt;a href=&#34;#open&#34;&gt;open cursor&lt;/a&gt; to the next position without retrieving the row. The special &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/embedded-sql/#found&#34;&gt;FOUND&lt;/a&gt; variable is set to &lt;code&gt;true&lt;/code&gt; if the cursor&#39;s position (before MOVE) was not past the final row—that is, if calling FETCH instead of MOVE would have retrieved the row.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;MOVE &lt;span class=&#34;code-variable&#34;&gt;bound_cursor&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, this cursor only retrieves rows where the y-coordinate is 2. The result set is only one row, so using MOVE twice advances past the first (and last) row, setting FOUND to false:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; =&amp;gt; SELECT * FROM coordinates WHERE y=2;
 x  | y | z
----+---+---
 10 | 2 | 1
(1 row)

DO $$
DECLARE
    c CURSOR (key int) FOR SELECT * FROM coordinates WHERE y=key;
BEGIN
    OPEN c(2); -- only retrieve rows where y=2, cursor starts before the first row
    MOVE c; -- cursor advances to the first (and last) row
    RAISE NOTICE &amp;#39;FOUND=%&amp;#39;, FOUND; -- FOUND is true because the cursor points to a row in the result set
    MOVE c; -- cursor advances past the final row
    RAISE NOTICE &amp;#39;FOUND=%&amp;#39;, FOUND; -- FOUND is false because the cursor is past the final row
END;
$$;

NOTICE 2005:  FOUND=t
NOTICE 2005:  FOUND=f
&lt;/code&gt;&lt;/pre&gt;
      </description>
    </item>
    
    <item>
      <title>Extending: PL/pgSQL to PL/vSQL migration guide</title>
      <link>/en/extending/stored-procedures/plvsql/plpgsql-to-plvsql-migration/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/extending/stored-procedures/plvsql/plpgsql-to-plvsql-migration/</guid>
      <description>
        
        
        &lt;p&gt;While OpenText™ Analytics Database PL/vSQL is largely compatible with PostgreSQL PL/pgSQL, there are some easily-resolved semantic and SQL-level differences when migrating from PostgreSQL PL/pgSQL.&lt;/p&gt;
&lt;h2 id=&#34;language-level-differences&#34;&gt;Language-level differences&lt;/h2&gt;
&lt;p&gt;PL/vSQL differs from PL/pgSQL in the following ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You must use the &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/embedded-sql/#perform&#34;&gt;PERFORM&lt;/a&gt; statement for SQL statements that return no value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.postgresql.org/docs/current/plpgsql-cursors.html#PLPGSQL-CURSOR-USING&#34;&gt;UPDATE/DELETE WHERE CURRENT OF&lt;/a&gt; is not currently supported.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/control-flow/&#34;&gt;FOR&lt;/a&gt; loops have additional keywords:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;FOR (RANGE) loops: RANGE keyword&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;FOR (QUERY) loops: QUERY keyword&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;FOR (CURSOR) loops: CURSOR keyword&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;By default, NULL cannot be coerced to FALSE.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;coercing-null-to-false&#34;&gt;Coercing NULL to FALSE&lt;/h3&gt;
&lt;p&gt;NULL is not coercible to FALSE by default, and expressions that expect a BOOLEAN value throw an exception when given a NULL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BEGIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;IF&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;THEN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- BOOLEAN value expected for IF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;END&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;IF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;END&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ERROR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10268&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Query&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;returned&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;was&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expected&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To enable NULL-to-FALSE coercion, set the configuration parameter PLvSQLCoerceNull:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ALTER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DATABASE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DEFAULT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SET&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLvSQLCoerceNull&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;planned-features&#34;&gt;Planned features&lt;/h2&gt;
&lt;p&gt;Support for the following features is planned for a future release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Full transaction semantics: Currently, stored procedures only &lt;a href=&#34;../../../../en/sql-reference/statements/commit/#&#34;&gt;COMMIT&lt;/a&gt; changes after successful execution. This means that you cannot manually &lt;a href=&#34;../../../../en/sql-reference/statements/rollback/#&#34;&gt;ROLLBACK&lt;/a&gt;. However, changes made by &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/scope-and-structure/#nested-stored-procedures&#34;&gt;nested stored procedures&lt;/a&gt; are automatically rolled back if they reach the depth limit. You can also use PERFORM &lt;a href=&#34;../../../../en/sql-reference/statements/commit/#&#34;&gt;COMMIT&lt;/a&gt; to commit changes during execution.&lt;/li&gt;
&lt;li&gt;FOREACH (ARRAY) &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/control-flow/&#34;&gt;loops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Using the following types as arguments:
&lt;ul&gt;
&lt;li&gt;DECIMAL&lt;/li&gt;
&lt;li&gt;NUMERIC&lt;/li&gt;
&lt;li&gt;NUMBER&lt;/li&gt;
&lt;li&gt;MONEY&lt;/li&gt;
&lt;li&gt;UUID&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Non-forward moving &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/cursors/&#34;&gt;cursors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CONTEXT/EXCEPTION_CONTEXT for &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/errors-and-diagnostics/&#34;&gt;diagnostics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The special variable ROW_COUNT: To work around this, you can rely on INSERT, UPDATE, and DELETE to return the number of rows affected:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DECLARE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BEGIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INSERT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;INTO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;VALUES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RAISE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;INFO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;rows inserted: %&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;END&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;$$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;INFO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2005&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;inserted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;sql-level-differences&#34;&gt;SQL-level differences&lt;/h2&gt;
&lt;p&gt;OpenText™ Analytics Database differs from PostgreSQL in the following ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Some &lt;a href=&#34;../../../../en/sql-reference/data-types/&#34;&gt;data types&lt;/a&gt; are different sizes—for example, the standard INTEGER type in the database is 8 bytes, but 4 bytes in PostgreSQL.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;INSERT, UPDATE, and DELETE return the number of rows affected.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Certain SQLSTATE codes are different, which affects &lt;a href=&#34;../../../../en/extending/stored-procedures/plvsql/errors-and-diagnostics/&#34;&gt;exception handling&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
  </channel>
</rss>
