<html>
<head>
    <base href="https://docs.jboss.org/author">
            <link rel="stylesheet" href="/author/s/en/2172/19/5/_/styles/combined.css?spaceKey=TEIID&amp;forWysiwyg=true" type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://docs.jboss.org/author/display/TEIID/Procedure+Language">Procedure Language</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://docs.jboss.org/author/display/~shawkins">Steven Hawkins</a>
    </h4>
        <br/>
                         <h4>Changes (1)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >{code} <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">The criteria may be any valid boolean expression or an IS DISTINCT FROM predicate.  IS DISTINCT FROM uses the syntax: <br> <br>{code:SQL} <br>rowVal IS [NOT] DISTINCT FROM rowValOther <br>{code} <br> <br>Where rowVal and rowValOther are references to row value group.  This would typically be used in instead of update triggers on views to quickly determine if the row values are changing: <br> <br>{code:title=Example IS DISTINCT FROM If Statement} <br>IF ( &quot;new&quot; IS DISTINCT FROM &quot;old&quot;) <br>BEGIN <br>  ...statement... <br>END  <br>{code} <br> <br>IS DISTINCT FROM considers null values equivalent and never produces an UNKNOWN value. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >{tip:title=Tip}NULL values should be considered in the criteria of an IF statement.  IS NULL criteria can be used to detect the presence of a NULL value. <br>{tip} <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p>Teiid supports a procedural language for defining <a href="/author/display/TEIID/Virtual+Procedures" title="Virtual Procedures">Virtual Procedures</a>. These are similar to stored procedures in relational database management systems. You can use this language to define the transformation logic for decomposing INSERT, UPDATE, and DELETE commands against views; these are known as <a href="/author/display/TEIID/Update+Procedures" title="Update Procedures">Update Procedures</a>.</p>


<h1><a name="ProcedureLanguage-CommandStatement"></a>Command Statement</h1>

<p>A command statement executes a <a href="/author/display/TEIID/DML+Commands" title="DML Commands">DML Command</a>, such as SELECT, INSERT, UPDATE, DELETE, EXECUTE, or a DDL statement, dynamic SQL, etc.</p>

<p>Usage:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
command [(WITH|WITHOUT) RETURN];
</pre>
</div></div>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Command Statements</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">SELECT * FROM MySchema.MyTable WHERE ColA &gt; 100 WITHOUT RETURN;
INSERT INTO MySchema.MyTable (ColA,ColB) VALUES (50, 'hi');</pre>
</div></div>

<p>Syntax Rules:</p>

<ul>
        <li><a href="/author/display/TEIID/DML+Commands#DMLCommands-EXECUTECommand">EXECUTE</a> command statements may access IN/OUT, OUT, and RETURN parameters.  To access the return value the statement will have the form <tt>var = EXEC proc...</tt>. To access OUT or IN/OUT values named parameter syntax must be used.  For example, <tt>EXEC proc(in_param=&gt;'1', out_param=&gt;var)</tt> will assign the value of the out parameter to the variable var. It is expected that the datatype of parameter will be implicitly convertable to the datatype of the variable.</li>
</ul>


<ul>
        <li>The RETURN clause determines if the result of the command is returnable from the procedure. WITH RETURN is the default. If the command does not return a result set or the procedure does not return a result set, the RETURN clause is ignored. If WITH RETURN is specified, the result set of the command must match the expected result set of the procedure.  Only the last successfully executed statement executed WITH RETURN will be returned as the procedure result set.&nbsp; If there are no returnable result sets and the procedure declares that a result set will be returned, then an empty result set is returned.</li>
</ul>


<h1><a name="ProcedureLanguage-DynamicSQLCommand"></a>Dynamic SQL Command</h1>

<p>Dynamic SQL allows for the execution of an arbitrary SQL command in a virtual procedure. Dynamic SQL is useful in situations where the exact command form is not known prior to execution.</p>

<p>Usage:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
EXECUTE IMMEDIATE &lt;expression&gt; AS &lt;variable&gt; &lt;type&gt; [, &lt;variable&gt; &lt;type&gt;]* [INTO &lt;variable&gt;] [USING &lt;variable&gt;=&lt;expression&gt; [,&lt;variable&gt;=&lt;expression&gt;]*] [UPDATE &lt;literal&gt;]
</pre>
</div></div>

<p>Syntax Rules:</p>

<ul>
        <li>The "AS" clause is used to define the projected symbols names and types returned by the executed SQL string. The "AS" clause symbols will be matched positionally with the symbols returned by the executed SQL string. Non-convertible types or too few columns returned by the executed SQL string will result in an error.</li>
</ul>


<ul>
        <li>The "INTO" clause will project the dynamic SQL into the specified temp table. With the "INTO" clause specified, the dynamic command will actually execute a statement that behaves like an INSERT with a QUERY EXPRESSION. If the dynamic SQL command creates a temporary table with the "INTO" clause, then the "AS" clause is required to define the table's metadata.</li>
</ul>


<ul>
        <li>The "USING" clause allows the dynamic SQL string to contain variable references that are bound at runtime to specified values. This allows for some independence of the SQL string from the surrounding procedure variable names and input names. In the dynamic command "USING" clause, each variable is specified by short name only. However in the dynamic SQL the "USING" variable must be fully qualified to "DVAR.". The "USING" clause is only for values that will be used in the dynamic SQL as legal expressions. It is not possible to use the "USING" clause to replace table names, keywords, etc. This makes using symbols equivalent in power to normal bind &#40;?) expressions in prepared statements. The "USING" clause helps reduce the amount of string manipulation needed. If a reference is made to a USING symbol in the SQL string that is not bound to a value in the "USING" clause, an exception will occur.</li>
</ul>


<ul>
        <li>The "UPDATE" clause is used to specify the <a href="/author/display/TEIID/Updating+Model+Count" title="Updating Model Count">Updating Model Count</a>. Accepted values are (0,1,*). 0 is the default value if the clause is not specified.</li>
</ul>


<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Dynamic SQL</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">...
/* Typically complex criteria would be formed based upon inputs to the procedure.
 In this simple example the criteria is references the using clause to isolate
 the SQL string from referencing a value from the procedure directly */

DECLARE string criteria = 'Customer.Accounts.Last = DVARS.LastName';

/* Now we create the desired SQL string */
DECLARE string sql_string = 'SELECT ID, First || '' '' || Last AS Name, Birthdate FROM Customer.Accounts WHERE ' || criteria;

/* The execution of the SQL string will create the #temp table with the columns (ID, Name, Birthdate).
  Note that we also have the USING clause to bind a value to LastName, which is referenced in the criteria. */
EXECUTE IMMEDIATE sql_string AS ID integer, Name string, Birthdate date INTO #temp USING LastName='some name';

/* The temp table can now be used with the values from the Dynamic SQL */
loop on (SELCT ID from #temp) as myCursor
...</pre>
</div></div>

<p>Here is an example showing a more complex approach to building criteria for the dynamic SQL string. In short, the virtual procedure AccountAccess.GetAccounts has inputs ID, LastName, and bday. If a value is specified for ID it will be the only value used in the dynamic SQL criteria. Otherwise if a value is specified for LastName the procedure will detect if the value is a search string. If bday is specified in addition to LastName, it will be used to form compound criteria with LastName.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Dynamic SQL with USING clause and dynamically built criteria string</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
...
DECLARE string crit = null;

IF (AccountAccess.GetAccounts.ID IS NOT NULL)
 crit = '(Customer.Accounts.ID = DVARS.ID)';
ELSE IF (AccountAccess.GetAccounts.LastName IS NOT NULL)
BEGIN
 IF (AccountAccess.GetAccounts.LastName == '%')
   ERROR "Last name cannot be %";
 ELSE IF (LOCATE('%', AccountAccess.GetAccounts.LastName) &lt; 0)
   crit = '(Customer.Accounts.Last = DVARS.LastName)';
 ELSE
   crit = '(Customer.Accounts.Last LIKE DVARS.LastName)';
 IF (AccountAccess.GetAccounts.bday IS NOT NULL)
   crit = '(' || crit || ' and (Customer.Accounts.Birthdate = DVARS.BirthDay))';
END
ELSE
 ERROR "ID or LastName must be specified.";

EXECUTE IMMEDIATE 'SELECT ID, First || '' '' || Last AS Name, Birthdate FROM Customer.Accounts WHERE ' || crit USING ID=AccountAccess.GetAccounts.ID, LastName=AccountAccess.GetAccounts.LastName, BirthDay=AccountAccess.GetAccounts.Bday;
...
</pre>
</div></div>
<p>Known Limitations and Work-Arounds</p>

<p>The use of dynamic SQL command results in an assignment statement requires the use of a temp table.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Assignment</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
EXECUTE IMMEDIATE &lt;expression&gt; AS x string INTO #temp;
DECLARE string VARIABLES.RESULT = (SELECT x FROM #temp);
</pre>
</div></div>

<p>The construction of appropriate criteria will be cumbersome if parts of the criteria are not present. For example if "criteria" were already NULL, then the following example results in "criteria" remaining NULL.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Dangerous NULL handling</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
...
criteria = '(' || criteria || ' and (Customer.Accounts.Birthdate = DVARS.BirthDay))';</pre>
</div></div>
<p>The preferred approach is for the user to ensure the criteria is not NULL prior its usage. If this is not possible, a good approach is to specify a default as shown in the following example.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example NULL handling</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">...
criteria = '(' || nvl(criteria, '(1 = 1)') || ' and (Customer.Accounts.Birthdate = DVARS.BirthDay))';</pre>
</div></div>

<p>If the dynamic SQL is an UPDATE, DELETE, or INSERT command, the rowcount of the statement can be obtained from the rowcount variable.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example with AS and INTO clauses</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
/* Execute an update */
EXECUTE IMMEDIATE &lt;expression&gt;;

</pre>
</div></div>

<ul>
        <li>Unless used in other parts of the procedure, tables in the dynamic command will not be seen as sources in the Designer.</li>
</ul>


<ul>
        <li>When using the "AS" clause only the type information will be available to the Designer. ResultSet columns generated from the "AS" clause then will have a default set of properties for length, precision, etc.</li>
</ul>


<h1><a name="ProcedureLanguage-DeclarationStatement"></a>Declaration Statement</h1>

<p>A declaration statement declares a variable and its type. After you declare a variable, you can use it in that block within the procedure and any sub-blocks. A variable is initialized to null by default, but can also be assigned the value of an expression as part of the declaration statement.</p>

<p>Usage:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">DECLARE &lt;type&gt; [VARIABLES.]&lt;name&gt; [= &lt;expression&gt;];</pre>
</div></div>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Syntax</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
  declare integer x;
  declare string VARIABLES.myvar = 'value';
</pre>
</div></div>

<p>Syntax Rules:</p>

<ul>
        <li>You cannot redeclare a variable with a duplicate name in a sub-block</li>
        <li>The VARIABLES group is always implied even if it is not specified.</li>
        <li>The assignment value follows the same rules as for an Assignment Statement.</li>
        <li>In addition to the standard types, you may specify EXCEPTION if declaring an exception variable.</li>
</ul>


<h1><a name="ProcedureLanguage-AssignmentStatement"></a>Assignment Statement</h1>

<p>An assignment statement assigns a value to a variable by either evaluating an expression.</p>

<p>Usage:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">&lt;variable reference&gt; = &lt;expression&gt;;</pre>
</div></div>

<p>Example Syntax</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
myString = 'Thank you';
VARIABLES.x = (SELECT Column1 FROM MySchema.MyTable);
</pre>
</div></div>

<h2><a name="ProcedureLanguage-SpecialVariables"></a>Special Variables</h2>

<p><em>VARIABLES.ROWCOUNT</em> integer variable will contain the numbers of rows affected by the last insert/update/delete command statement executed.  Inserts that are processed by dynamic sql with an into clause will also update the <em>ROWCOUNT</em>.</p>

<p>Usage:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Sample Usage</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
...
UPDATE FOO SET X = 1 WHERE Y = 2;
DECLARE INTEGER UPDATED = VARIABLES.ROWCOUNT;
...
</pre>
</div></div>

<p>Non-update command statements (WITH or WITHOUT RETURN) will reset the ROWCOUNT to 0.  </p>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/author/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>To ensure you are getting the appropriate ROWCOUNT value, save the ROWCOUNT to a variable immediately after the command statement.</td></tr></table></div>

<h1><a name="ProcedureLanguage-CompoundStatement"></a>Compound Statement</h1>

<p>A compound statement or block logically groups a series of statements.  Temporary tables and variables created in a compound statement are local only to that block are destroyed when exiting the block.</p>

<p>Usage:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
[label :] BEGIN [[NOT] ATOMIC]
    statement*
[EXCEPTION ex
    statement*
]
END
</pre>
</div></div>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/author/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>When a block is expected by a IF, LOOP, WHILE, etc. a single statement is also accepted by the parser.  Even though the block BEGIN/END are not expected, the statement will execute as if wrapped in a BEGIN/END pair.</td></tr></table></div>

<p>Syntax Rules</p>

<ul>
        <li>IF NOT ATOMIC or no ATOMIC clause is specified, the block will be executed non-atomically.</li>
</ul>


<ul>
        <li>IF ATOMIC the block must execute atomically.  If a transaction is already associated with the thread, no additional action will be taken - savepoints and/or sub-transactions are not currently used.  If the higher level transaction is used and the block does not complete - regardless of the presence of exception handling the transaction will be marked as rollback only.  Otherwise a transaction will be associated with the execution of the block.  Upon successful completion of the block the transaction will be committed.</li>
</ul>


<ul>
        <li>The label must not be the same as any other label used in statements containing this one.</li>
</ul>


<ul>
        <li>Variable assignments and the implicit result cursor are unaffected by rollbacks.  If a block does not complete successfully its assignments will still take affect.</li>
</ul>


<h3><a name="ProcedureLanguage-ExceptionHandling"></a>Exception Handling</h3>

<p>If the EXCEPTION clause is used with in a compound statement, any processing exception emitted from statements will be caught with the flow of execution transferring to EXCEPTION statements.  Any block level transaction started by this block will commit if the exception handler successfully completes.  If another exception or the original exception is emitted from the exception handler the transaction will rollback.  Any temporary tables or variables specific to the BLOCK will not be available to the exception handler statements.</p>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/author/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>Only processing exceptions, which are typically caused by errors originating at the sources or with function execution, are caught.  A low-level internal Teiid error or Java <tt>RuntimeException</tt> will not be caught.</td></tr></table></div>

<p>To aid in the processing of a caught exception the EXCEPTION clause specifies a group name that exposes the significant fields of the exception.  The exception group will contain:</p>
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Variable </th>
<th class='confluenceTh'> Type </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> STATE </td>
<td class='confluenceTd'> string </td>
<td class='confluenceTd'> The SQL State </td>
</tr>
<tr>
<td class='confluenceTd'> ERRORCODE </td>
<td class='confluenceTd'> integer </td>
<td class='confluenceTd'> The error or vendor code.  In the case of Teiid internal exceptions this will be the integer suffix of the TEIIDxxxx code </td>
</tr>
<tr>
<td class='confluenceTd'> TEIIDCODE </td>
<td class='confluenceTd'> string </td>
<td class='confluenceTd'> The full Teiid event code.  Typically TEIIDxxxx. </td>
</tr>
<tr>
<td class='confluenceTd'> EXCEPTION </td>
<td class='confluenceTd'> object </td>
<td class='confluenceTd'> The exception being caught, will be an instance of <tt>TeiidSQLException</tt> </td>
</tr>
<tr>
<td class='confluenceTd'> CHAIN </td>
<td class='confluenceTd'> object </td>
<td class='confluenceTd'> The chained exception or cause of the current exception </td>
</tr>
</tbody></table>
</div>


<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/author/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>Teiid does not yet fully comply with the ANSI SQL specification on SQL State usage.  For Teiid errors without an underlying SQLException cause, it is best to use the Teiid code.</td></tr></table></div>

<p>The exception group name may not be the same as any higher level exception group or loop cursor name.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Exception Group Handling</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
BEGIN
    DECLARE EXCEPTION e = SQLEXCEPTION 'this is bad' SQLSTATE 'xxxxx';
    RAISE variables.e;
EXCEPTION e
    IF (e.state = 'xxxxx')
        //in this trivial example, we'll always hit this branch and just log the exception
        RAISE SQLWARNING e.exception;
    ELSE
        RAISE e.exception;
END
</pre>
</div></div>

<h1><a name="ProcedureLanguage-IfStatement"></a>If Statement</h1>

<p>An IF statement evaluates a condition and executes either one of two statements depending on the result. You can nest IF statements to create complex branching logic. A dependent ELSE statement will execute its statement only if the IF statement evaluates to false.</p>

<p>Usage:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
IF (criteria)
   block
[ELSE
   block]
END
</pre>
</div></div>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example If Statement</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
IF ( var1 = 'North America')
BEGIN
  ...statement...
END ELSE
BEGIN
  ...statement...
END
</pre>
</div></div>

<p>The criteria may be any valid boolean expression or an IS DISTINCT FROM predicate.  IS DISTINCT FROM uses the syntax:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
rowVal IS [NOT] DISTINCT FROM rowValOther
</pre>
</div></div>

<p>Where rowVal and rowValOther are references to row value group.  This would typically be used in instead of update triggers on views to quickly determine if the row values are changing:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example IS DISTINCT FROM If Statement</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: java; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
IF ( "new" IS DISTINCT FROM "old")
BEGIN
  ...statement...
END 
</pre>
</div></div>

<p>IS DISTINCT FROM considers null values equivalent and never produces an UNKNOWN value.</p>

<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/author/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Tip</b><br />NULL values should be considered in the criteria of an IF statement.  IS NULL criteria can be used to detect the presence of a NULL value.</td></tr></table></div>

<h1><a name="ProcedureLanguage-LoopStatement"></a>Loop Statement</h1>

<p>A LOOP statement is an iterative control construct that is used to cursor through a result set.</p>

<p>Usage:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
[label :] LOOP ON &lt;select statement&gt; AS &lt;cursorname&gt;
    statement
</pre>
</div></div>

<p>Syntax Rules</p>

<ul>
        <li>The label must not be the same as any other label used in statements containing this one.</li>
</ul>


<h1><a name="ProcedureLanguage-WhileStatement"></a>While Statement</h1>

<p>A WHILE statement is an iterative control construct that is used to execute a statement repeatedly whenever a specified condition is met.</p>

<p>Usage:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
[label :] WHILE &lt;criteria&gt;
    statement
</pre>
</div></div>

<p>Syntax Rules</p>

<ul>
        <li>The label must not be the same as any other label used in statements containing this one.</li>
</ul>


<h1><a name="ProcedureLanguage-ContinueStatement"></a>Continue Statement</h1>

<p>A CONTINUE statement is used inside a LOOP or WHILE construct to continue with the next loop by skipping over the rest of the statements in the loop. It must be used inside a LOOP or WHILE statement.</p>

<p>Usage: <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">CONTINUE [label];</pre>
</div></div></p>

<p>Syntax Rules</p>

<ul>
        <li>If the label is specified, it must exist on a containing LOOP or WHILE statement.</li>
</ul>


<ul>
        <li>If no label is specified, the statement will affect the closest containing LOOP or WHILE statement.</li>
</ul>


<h1><a name="ProcedureLanguage-BreakStatement"></a>Break Statement</h1>

<p>A BREAK statement is used inside a LOOP or WHILE construct to break from the loop. It must be used inside a LOOP or WHILE statement.</p>

<p>Usage: <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">BREAK [label];</pre>
</div></div></p>

<p>Syntax Rules</p>

<ul>
        <li>If the label is specified, it must exist on a containing LOOP or WHILE statement.</li>
</ul>


<ul>
        <li>If no label is specified, the statement will affect the closest containing LOOP or WHILE statement.</li>
</ul>


<h1><a name="ProcedureLanguage-LeaveStatement"></a>Leave Statement</h1>

<p>A LEAVE statement is used inside a compound, LOOP, or WHILE construct to leave to the specified level.</p>

<p>Usage: <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">LEAVE label;</pre>
</div></div></p>

<p>Syntax Rules</p>

<ul>
        <li>The label must exist on a containing compound statement, LOOP, or WHILE statement.</li>
</ul>


<h1><a name="ProcedureLanguage-ReturnStatement"></a>Return Statement</h1>

<p>A Return statement gracefully exits the procedure and optionally returns a value.</p>

<p>Usage: <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">RETURN [expression];</pre>
</div></div></p>

<p>Syntax Rules</p>

<ul>
        <li>If an expression is specified, the procedure must have a return parameter and the value must be implicitly convertable to the expected type.</li>
</ul>


<ul>
        <li>Even if the procedure has a return value, it is not required to specify a return value in a RETURN statement.</li>
</ul>


<h1><a name="ProcedureLanguage-ErrorStatement"></a>Error Statement</h1>

<p>An ERROR statement declares that the procedure has entered an error state and should abort. This statement will also roll back the current transaction, if one exists. Any valid expression can be specified after the ERROR keyword.</p>

<p>Usage: <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">ERROR message;</pre>
</div></div></p>

<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Error Statement</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
ERROR 'Invalid input value: ' || nvl(Acct.GetBalance.AcctID, 'null');
</pre>
</div></div>

<p>An ERROR statement is equivalent to: <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">RAISE SQLEXCEPTION message;</pre>
</div></div></p>

<h1><a name="ProcedureLanguage-RaiseStatement"></a>Raise Statement</h1>

<p>A RAISE statement is used to raise an exception or warning. When raising an exception, this statement will also roll back the current transaction, if one exists.</p>

<p>Usage: <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">RAISE [SQLWARNING] exception;</pre>
</div></div><br/>
Where exception may be a variable reference to an exception or an exception expression.</p>

<p>Syntax Rules</p>

<ul>
        <li>If SQLWARNING is specified, the exception will be sent to the client as a warning and the procedure will continue to execute.</li>
</ul>


<ul>
        <li>A null warning will be ignored.  A null non-warning exception will still cause an exception to be raised.</li>
</ul>


<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>Example Raise Statement</b></div><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">
RAISE SQLWARNING SQLEXCEPTION 'invalid' SQLSTATE '05000';
</pre>
</div></div>

<h1><a name="ProcedureLanguage-ExceptionExpression"></a>Exception Expression</h1>

<p>An exception expression creates an exception that can be raised or used as a warning.</p>

<p>Usage: <div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: sql; gutter: false" style="font-size:12px; font-family: ConfluenceInstalledFont,monospace;">SQLEXCEPTION message [SQLSTATE state [, code]] CHAIN exception</pre>
</div></div></p>

<p>Syntax Rules</p>

<ul>
        <li>Any of the values may be null;</li>
        <li>message and state are string expressions specifying the exception message and SQL state respectively.  Teiid does not yet fully comply with the ANSI SQL specification on SQL state usage, but you are allowed to set any SQL state you choose.</li>
        <li>code is an integer expression specifying the vendor code</li>
        <li>exception must be a variable reference to an exception or an exception expression and will be chained to the resulting exception as its parent.</li>
</ul>

    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;" class="grey">
                        <a href="https://docs.jboss.org/author/users/removespacenotification.action?spaceKey=TEIID">Stop watching space</a>
            <span style="padding: 0px 5px;">|</span>
                <a href="https://docs.jboss.org/author/users/editmyemailsettings.action">Change email notification preferences</a>
</div>
        <a href="https://docs.jboss.org/author/display/TEIID/Procedure+Language">View Online</a>
        |
        <a href="https://docs.jboss.org/author/pages/diffpagesbyversion.action?pageId=18646266&revisedVersion=18&originalVersion=17">View Changes</a>
                |
        <a href="https://docs.jboss.org/author/display/TEIID/Procedure+Language?showComments=true&amp;showCommentArea=true#addcomment">Add Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>