ibm-information-center/dist/eclipse/plugins/i5OS.ic.sqlp_5.4.0.1/rbafysqlproc.htm

340 lines
20 KiB
HTML
Raw Normal View History

2024-04-02 14:02:31 +00:00
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-us" xml:lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="security" content="public" />
<meta name="Robots" content="index,follow" />
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
<meta name="DC.Type" content="reference" />
<meta name="DC.Title" content="Define an SQL procedure" />
<meta name="abstract" content="The CREATE PROCEDURE statement for SQL procedures names the procedure, defines the parameters and their attributes, provides other information about the procedure that is used when the procedure is called, and defines the procedure body. The procedure body is the executable part of the procedure and is a single SQL statement." />
<meta name="description" content="The CREATE PROCEDURE statement for SQL procedures names the procedure, defines the parameters and their attributes, provides other information about the procedure that is used when the procedure is called, and defines the procedure body. The procedure body is the executable part of the procedure and is a single SQL statement." />
<meta name="DC.subject" content="stored procedures, defining SQL, CREATE PROCEDURE statement, statements, CREATE PROCEDURE, examples, defining stored procedures, with CREATE PROCEDURE" />
<meta name="keywords" content="stored procedures, defining SQL, CREATE PROCEDURE statement, statements, CREATE PROCEDURE, examples, defining stored procedures, with CREATE PROCEDURE" />
<meta name="DC.Relation" scheme="URI" content="rbafysproeg.htm" />
<meta name="copyright" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Format" content="XHTML" />
<meta name="DC.Identifier" content="rbafysqlproc" />
<meta name="DC.Language" content="en-us" />
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
<link rel="stylesheet" type="text/css" href="./ic.css" />
<title>Define an SQL procedure</title>
</head>
<body id="rbafysqlproc"><a name="rbafysqlproc"><!-- --></a>
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<h1 class="topictitle1">Define an SQL procedure</h1>
<div><p>The CREATE PROCEDURE statement for SQL procedures names the procedure,
defines the parameters and their attributes, provides other information about
the procedure that is used when the procedure is called, and defines the procedure
body. The <dfn class="term">procedure body</dfn> is the executable part of the procedure
and is a single SQL statement.</p>
<div class="section"><p>Consider the following simple example that takes as input an employee
number and a rate and updates the employee's salary: </p>
<pre> <strong>CREATE PROCEDURE</strong> UPDATE_SALARY_1
(<strong>IN</strong> EMPLOYEE_NUMBER <strong>CHAR</strong>(10),
<strong>IN</strong> RATE <strong>DECIMAL</strong>(6,2))
<strong>LANGUAGE SQL MODIFIES SQL DATA</strong>
<strong>UPDATE</strong> CORPDATA.EMPLOYEE
<strong>SET</strong> SALARY = SALARY * RATE
<strong>WHERE</strong> EMPNO = EMPLOYEE_NUMBER </pre>
</div>
<div class="section"><p>This CREATE PROCEDURE statement: </p>
<ul><li>Names the procedure UPDATE_SALARY_1.</li>
<li>Defines parameter EMPLOYEE_NUMBER which is an input parameter and is a
character data type of length 6 and parameter RATE which is an input parameter
and is a decimal data type.</li>
<li>Indicates the procedure is an SQL procedure that modifies SQL data.</li>
<li>Defines the procedure body as a single UPDATE statement. When the procedure
is called, the UPDATE statement is executed using the values passed for EMPLOYEE_NUMBER
and RATE.</li>
</ul>
</div>
<div class="section"><p>Instead of a single UPDATE statement, logic can be added to the
SQL procedure using SQL control statements. SQL control statements consist
of: </p>
<ul><li>An assignment statement</li>
<li>A CALL statement</li>
<li>A CASE statement</li>
<li>A compound statement</li>
<li>A FOR statement</li>
<li>A GET DIAGNOSTICS statement</li>
<li>A GOTO statement</li>
<li>An IF statement</li>
<li>an ITERATE statement</li>
<li>a LEAVE statement</li>
<li>a LOOP statement</li>
<li>a REPEAT statement</li>
<li>a RESIGNAL statement</li>
<li>a RETURN statement</li>
<li>a SIGNAL statement</li>
<li>a WHILE statement</li>
</ul>
</div>
<div class="section"><p>The following example takes as input the employee number and a
rating that was received on the last evaluation. The procedure uses a CASE
statement to determine the appropriate increase and bonus for the update.</p>
<pre> <strong>CREATE PROCEDURE</strong> UPDATE_SALARY_2
(<strong>IN</strong> EMPLOYEE_NUMBER <strong>CHAR</strong>(6),
<strong>IN</strong> RATING <strong>INT</strong>)
<strong>LANGUAGE SQL MODIFIES SQL DATA</strong>
<strong>CASE</strong> RATING
<strong>WHEN</strong> 1 <strong>THEN</strong>
<strong>UPDATE</strong> CORPDATA.EMPLOYEE
<strong>SET</strong> SALARY = SALARY * 1.10,
BONUS = 1000
<strong>WHERE</strong> EMPNO = EMPLOYEE_NUMBER;
<strong>WHEN</strong> 2 <strong>THEN</strong>
<strong>UPDATE</strong> CORPDATA.EMPLOYEE
<strong>SET</strong> SALARY = SALARY * 1.05,
BONUS = 500
<strong>WHERE</strong> EMPNO = EMPLOYEE_NUMBER;
<strong>ELSE</strong>
<strong>UPDATE</strong> CORPDATA.EMPLOYEE
<strong>SET</strong> SALARY = SALARY * 1.03,
BONUS = 0
<strong>WHERE</strong> EMPNO = EMPLOYEE_NUMBER;
<strong>END CASE</strong></pre>
</div>
<div class="section"><p>This CREATE PROCEDURE statement: </p>
<ul><li>Names the procedure UPDATE_SALARY_2.</li>
<li>Defines parameter EMPLOYEE_NUMBER which is an input parameter and is a
character data type of length 6 and parameter RATING which is an input parameter
and is an integer data type.</li>
<li>Indicates the procedure is an SQL procedure that modifies SQL data.</li>
<li>Defines the procedure body. When the procedure is called, input parameter
RATING is checked and the appropriate update statement is executed.</li>
</ul>
</div>
<div class="section"><p>Multiple statements can be added to a procedure body by adding
a compound statement. Within a compound statement, any number of SQL statements
can be specified. In addition, SQL variables, cursors, and handlers can be
declared.</p>
</div>
<div class="section"><p>The following example takes as input the department number. It
returns the total salary of all the employees in that department and the number
of employees in that department who get a bonus. </p>
<pre><strong>CREATE PROCEDURE </strong>RETURN_DEPT_SALARY
(<strong>IN</strong> DEPT_NUMBER <strong>CHAR</strong>(3),
<strong>OUT</strong> DEPT_SALARY <strong>DECIMAL</strong>(15,2),
<strong>OUT</strong> DEPT_BONUS_CNT <strong>INT</strong>)
<strong>LANGUAGE SQL READS SQL DATA</strong>
P1: <strong>BEGIN</strong>
<strong>DECLARE</strong> EMPLOYEE_SALARY <strong>DECIMAL</strong>(9,2);
<strong>DECLARE</strong> EMPLOYEE_BONUS <strong>DECIMAL</strong>(9,2);
<strong>DECLARE</strong> TOTAL_SALARY <strong>DECIMAL</strong>(15,2)<strong>DEFAULT</strong> 0;
<strong>DECLARE</strong> BONUS_CNT <strong>INT DEFAULT</strong> 0;
<strong>DECLARE</strong> END_TABLE <strong>INT DEFAULT</strong> 0;
<strong>DECLARE</strong> C1 <strong>CURSOR FOR
SELECT</strong> SALARY, BONUS <strong>FROM</strong> CORPDATA.EMPLOYEE
<strong>WHERE</strong> WORKDEPT = DEPT_NUMBER;
<strong>DECLARE CONTINUE HANDLER FOR NOT FOUND</strong>
<strong>SET</strong> END_TABLE = 1;
<strong>DECLARE EXIT HANDLER FOR SQLEXCEPTION</strong>
<strong>SET</strong> DEPT_SALARY = NULL;
<strong>OPEN</strong> C1;
<strong>FETCH</strong> C1 <strong>INTO</strong> EMPLOYEE_SALARY, EMPLOYEE_BONUS;
<strong>WHILE</strong> END_TABLE = 0 <strong>DO</strong>
<strong>SET</strong> TOTAL_SALARY = TOTAL_SALARY + EMPLOYEE_SALARY + EMPLOYEE_BONUS;
<strong>IF</strong> EMPLOYEE_BONUS &gt; 0 <strong>THEN</strong>
<strong>SET</strong> BONUS_CNT = BONUS_CNT + 1;
<strong>END IF;</strong>
<strong>FETCH</strong> C1 <strong>INTO</strong> EMPLOYEE_SALARY, EMPLOYEE_BONUS;
<strong>END WHILE;</strong>
<strong>CLOSE</strong> C1;
<strong>SET</strong> DEPT_SALARY = TOTAL_SALARY;
<strong>SET</strong> DEPT_BONUS_CNT = BONUS_CNT;
<strong>END</strong> P1 </pre>
</div>
<div class="section"><p>This CREATE PROCEDURE statement: </p>
<ul><li>Names the procedure RETURN_DEPT_SALARY.</li>
<li>Defines parameter DEPT_NUMBER which is an input parameter and is a character
data type of length 3, parameter DEPT_SALARY which is an output parameter
and is a decimal data type, and parameter DEPT_BONUS_CNT which is an output
parameter and is an integer data type.</li>
<li>Indicates the procedure is an SQL procedure that reads SQL data</li>
<li>Defines the procedure body. <ul><li>Declares SQL variables EMPLOYEE_SALARY and TOTAL_SALARY as decimal fields.</li>
<li>Declares SQL variables BONUS_CNT and END_TABLE which are integers and
are initialized to 0.</li>
<li>Declares cursor C1 that selects the columns from the employee table.</li>
<li>Declares a continue handler for NOT FOUND, which, when called sets variable
END_TABLE to 1. This handler is called when the FETCH has no more rows to
return. When the handler is called, SQLCODE and SQLSTATE are reinitialized
to 0.</li>
<li>Declares an exit handler for SQLEXCEPTION. If called, DEPT_SALARY is set
to NULL and the processing of the compound statement is terminated. This handler
is called if any errors occur, that is, the SQLSTATE class is not '00', '01'
or '02'. Since indicators are always passed to SQL procedures, the indicator
value for DEPT_SALARY is -1 when the procedure returns. If this handler is
called, SQLCODE and SQLSTATE are reinitialized to 0. <p>If the handler for
SQLEXCEPTION is not specified and an error occurs that is not handled in another
handler, execution of the compound statement is terminated and the error is
returned in the SQLCA. Similar to indicators, the SQLCA is always returned
from SQL procedures.</p>
</li>
<li>Includes an OPEN, FETCH, and CLOSE of cursor C1. If a CLOSE of the cursor
is not specified, the cursor is closed at the end of the compound statement
since SET RESULT SETS is not specified in the CREATE PROCEDURE statement.</li>
<li>Includes a WHILE statement which loops until the last record is fetched.
For each row retrieved, the TOTAL_SALARY is incremented and, if the employee's
bonus is more than 0, the BONUS_CNT is incremented.</li>
<li>Returns DEPT_SALARY and DEPT_BONUS_CNT as output parameters.</li>
</ul>
</li>
</ul>
</div>
<div class="section"><p>Compound statements can be made atomic so if an error occurs that
is not expected, the statements within the atomic statement are rolled back.
The atomic compound statements are implemented using SAVEPOINTS. If the compound
statement is successful, the transaction is committed.</p>
</div>
<div class="section"><p>The following example takes as input the department number. It
ensures the EMPLOYEE_BONUS table exists, and inserts the name of all employees
in the department who get a bonus. The procedure returns the total count of
all employees who get a bonus. </p>
<pre><strong>CREATE PROCEDURE </strong>CREATE_BONUS_TABLE
(<strong>IN</strong> DEPT_NUMBER <strong>CHAR</strong>(3),
<strong>INOUT</strong> CNT <strong>INT</strong>)
<strong>LANGUAGE SQL MODIFIES SQL DATA</strong>
CS1: <strong>BEGIN ATOMIC</strong>
<strong>DECLARE</strong> NAME <strong>VARCHAR</strong>(30) <strong>DEFAULT NULL</strong>;
<strong>DECLARE CONTINUE HANDLER FOR SQLSTATE</strong> '42710'
<strong>SELECT COUNT(*) INTO</strong> CNT
<strong>FROM</strong> DATALIB.EMPLOYEE_BONUS;
<strong>DECLARE CONTINUE HANDLER FOR SQLSTATE</strong> '23505'
<strong>SET </strong> CNT = CNT - 1;
<strong>DECLARE UNDO HANDLER FOR SQLEXCEPTION</strong>
<strong>SET</strong> CNT = <strong>NULL</strong>;
<strong>IF</strong> DEPT_NUMBER <strong>IS NOT NULL THEN</strong>
<strong>CREATE TABLE</strong> DATALIB.EMPLOYEE_BONUS
(FULLNAME <strong>VARCHAR</strong>(30),
BONUS <strong>DECIMAL</strong>(10,2),
<strong>PRIMARY KEY</strong> (FULLNAME));
FOR_1:<strong>FOR</strong> V1 <strong>AS</strong> C1 <strong>CURSOR FOR</strong>
<strong>SELECT</strong> FIRSTNME, MIDINIT, LASTNAME, BONUS
<strong>FROM</strong> CORPDATA.EMPLOYEE
<strong>WHERE</strong> WORKDEPT = CREATE_BONUS_TABLE.DEPT_NUMBER
<strong>DO</strong>
<strong>IF</strong> BONUS &gt; 0 <strong>THEN</strong>
<strong>SET</strong> NAME = FIRSTNME <strong>CONCAT</strong> ' ' <strong>CONCAT</strong>
MIDINIT <strong>CONCAT</strong> ' '<strong>CONCAT</strong> LASTNAME;
<strong>INSERT INTO</strong> DATALIB.EMPLOYEE_BONUS
<strong>VALUES</strong>(CS1.NAME, FOR_1.BONUS);
<strong>SET</strong> CNT = CNT + 1;
<strong>END IF;</strong>
<strong>END FOR</strong> FOR_1;
<strong>END IF</strong>;
<strong>END</strong> CS1 </pre>
</div>
<div class="section"><p>This CREATE PROCEDURE statement: </p>
<ul><li>Names the procedure CREATE_BONUS_TABLE.</li>
<li>Defines parameter DEPT_NUMBER which is an input parameter and is a character
data type of length 3 and parameter CNT which is an input/output parameter
and is an integer data type.</li>
<li>Indicates the procedure is an SQL procedure that modifies SQL data</li>
<li>Defines the procedure body. <ul><li>Declares SQL variable NAME as varying character.</li>
<li>Declares a continue handler for SQLSTATE 42710, table already exists.
If the EMPLOYEE_BONUS table already exists, the handler is called and retrieves
the number of records in the table. The SQLCODE and SQLSTATE are reset to
0 and processing continues with the FOR statement.</li>
<li>Declares a continue handler for SQLSTATE 23505, duplicate key. If the
procedure attempts to insert a name that already exists in the table, the
handler is called and decrements CNT. Processing continues on the SET statement
following the INSERT statement.</li>
<li>Declares an UNDO handler for SQLEXCEPTION. If called, the previous statements
are rolled back, CNT is set to 0, and processing continues after the compound
statement. In this case, since there is no statement following the compound
statement, the procedure returns.</li>
<li>Uses the FOR statement to declare cursor C1 to read the records from the
EMPLOYEE table. Within the FOR statement, the column names from the select
list are used as SQL variables that contain the data from the row fetched.
For each row, data from columns FIRSTNME, MIDINIT, and LASTNAME are concatenated
together with a blank in between and the result is put in SQL variable NAME.
SQL variables NAME and BONUS are inserted into the EMPLOYEE_BONUS table. Because
the data type of the select list items must be known when the procedure is
created, the table specified in the FOR statement must exist when the procedure
is created. <p>An SQL variable name can be qualified with the label name of
the FOR statement or compound statement in which it is defined. In the example,
FOR_1.BONUS refers to the SQL variable that contains the value of column BONUS
for each row selected. CS1.NAME is the variable NAME defined in the compound
statement with the beginning label CS1. Parameter names can also be qualified
with the procedure name. CREATE_BONUS_TABLE.DEPT_NUMBER is the DEPT_NUMBER
parameter for the procedure CREATE_BONUS_TABLE. If unqualified SQL variable
names are used in SQL statements where column names are also allowed, and
the variable name is the same as a column name, the name will be used to refer
to the column.</p>
</li>
</ul>
</li>
</ul>
</div>
<div class="section"><p>You can also use dynamic SQL in an SQL procedure. The following
example creates a table that contains all employees in a specific department.
The department number is passed as input to the procedure and is concatenated
to the table name. </p>
<pre><strong>CREATE PROCEDURE</strong> CREATE_DEPT_TABLE (<strong>IN</strong> P_DEPT <strong>CHAR</strong>(3))
<strong>LANGUAGE SQL</strong>
<strong>BEGIN</strong>
<strong>DECLARE</strong> STMT <strong>CHAR</strong>(1000);
<strong>DECLARE</strong> MESSAGE <strong>CHAR</strong>(20);
<strong>DECLARE</strong> TABLE_NAME <strong>CHAR</strong>(30);
<strong>DECLARE CONTINUE HANDLER FOR</strong> SQLEXCEPTION
<strong>SET</strong> MESSAGE = 'ok';
<strong>SET</strong> TABLE_NAME = 'CORPDATA.DEPT_' <strong>CONCAT</strong> P_DEPT <strong>CONCAT</strong> '_T';
<strong>SET</strong> STMT = '<strong>DROP TABLE</strong> ' <strong>CONCAT</strong> TABLE_NAME;
<strong>PREPARE</strong> S1 <strong>FROM</strong> STMT;
<strong>EXECUTE</strong> S1;
<strong>SET</strong> STMT = '<strong>CREATE TABLE</strong> ' <strong>CONCAT</strong> TABLE_NAME <strong>CONCAT</strong>
'( EMPNO <strong>CHAR</strong>(6) <strong>NOT NULL</strong>,
FIRSTNME <strong>VARCHAR</strong>(12) <strong>NOT NULL</strong>,
MIDINIT <strong>CHAR</strong>(1) <strong>NOT NULL</strong>,
LASTNAME <strong>CHAR</strong>(15) <strong>NOT NULL</strong>,
SALARY <strong>DECIMAL</strong>(9,2))';
<strong>PREPARE</strong> S2 <strong>FROM</strong> STMT;
<strong>EXECUTE</strong> S2;
<strong>SET</strong> STMT = '<strong>INSERT INTO</strong> ' <strong>CONCAT</strong> TABLE_NAME <strong>CONCAT</strong>
'<strong>SELECT</strong> EMPNO, FIRSTNME, MIDINIT, LASTNAME, SALARY
<strong>FROM</strong> CORPDATA.EMPLOYEE
<strong>WHERE</strong> WORKDEPT = ?';
<strong>PREPARE</strong> S3 <strong>FROM</strong> STMT;
<strong>EXECUTE</strong> S3 <strong>USING</strong> P_DEPT;
<strong>END</strong></pre>
<p>This CREATE PROCEDURE statement: </p>
<ul><li>Names the procedure CREATE_DEPT_TABLE</li>
<li>Defines parameter P_DEPT which is an input parameter and is a character
data type of length 3.</li>
<li>Indicates the procedure is an SQL procedure.</li>
<li>Defines the procedure body. <ul><li>Declares SQL variable STMT and an SQL variable TABLE_NAME as character.</li>
<li>Declares a CONTINUE handler. The procedure attempts to DROP the table
in case it already exists. If the table does not exist, the first EXECUTE
fails. With the handler, processing will continue.</li>
<li>Sets variable TABLE_NAME to 'DEPT_' followed by the characters passed
in parameter P_DEPT, followed by '_T'.</li>
<li>Sets variable STMT to the DROP statement, and prepares and executes the
statement.</li>
<li>Sets variable STMT to the CREATE statement, and prepares and executes
the statement.</li>
<li>Sets variable STMT to the INSERT statement, and prepares and executes
the statement. A parameter marker is specified in the where clause. When the
statement is executed, the variable P_DEPT is passed on the USING clause.</li>
</ul>
</li>
</ul>
<p>If the procedure is called passing value 'D21' for the department,
table DEPT_D21_T is created and the table is initialized with all the employees
that are in department 'D21'.</p>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="rbafysproeg.htm" title="A procedure (often called a stored procedure) is a program that can be called to perform operations that can include both host language statements and SQL statements. Procedures in SQL provide the same benefits as procedures in a host language.">Stored procedures</a></div>
</div>
</div>
</body>
</html>