Flylib.com

Books Software

 
 
 

Section 2.9. Calling Stored Programs from Stored Programs


2.9. Calling Stored Programs from Stored Programs

Calling one stored program from another is perfectly simple. You do this with the CALL statement, just as you would from the MySQL command-line client.

Figure 2-15 shows a simple stored procedure that chooses between two stored procedures based on an input parameter. The output of the stored procedure ( l_bonus_amount is populated from an OUT parameter) is passed to a third procedure.

Here is an explanation of the significant lines:

Line(s)

Explanation

11

Determine if the employee is a manager. If he is a manager, we call the calc_manager_bonus stored procedure; if he is not a manager, we call the calc_minion_bonus stored procedure.

12 and 14

With both stored procedures, pass in the employee_id and provide a variable l_bonus_amount to receive the output of the stored procedure.

16

Call the grant_bonus stored procedure that passes as arguments the employee_id and the bonus amount, as calculated by the stored procedure we called in line 12 or 14.


Figure 2-15. Example of calling one stored procedure from another



2.10. Putting It All Together

In Example 2-7 we show a stored procedure that uses all the features of the stored program language we have covered so far in this tutorial.

Example 2-7. A more complex stored procedure
1  CREATE PROCEDURE putting_it_all_together(in_department_id INT)
2      MODIFIES SQL DATA
3  BEGIN
4      DECLARE l_employee_id INT;
5      DECLARE l_salary      NUMERIC(8,2);
6     DECLARE l_department_id INT;
7     DECLARE l_new_salary  NUMERIC(8,2);
8     DECLARE done          INT DEFAULT 0;
9
10    DECLARE cur1 CURSOR FOR
11             SELECT employee_id, salary, department_id
12               FROM employees
13              WHERE department_id=in_department_id;
14
15
16          DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
17
18     CREATE TEMPORARY TABLE IF NOT EXISTS emp_raises
19       (employee_id INT, department_id INT, new_salary NUMERIC(8,2));
20
21     OPEN cur1;
22     emp_loop: LOOP
23
24       FETCH cur1 INTO l_employee_id, l_salary, l_department_id;
25
26       IF done=1 THEN       /* No more rows*/
27          LEAVE emp_loop;
28       END IF;
29
30       CALL new_salary(l_employee_id,l_new_salary); /*get new salary*/
31
32       IF (l_new_salary<>l_salary) THEN             /*Salary changed*/
33
34          UPDATE employees
35             SET salary=l_new_salary
36           WHERE employee_id=l_employee_id;
37          /* Keep track of changed salaries*/
38          INSERT INTO emp_raises (employee_id,department_id,new_salary)
39           VALUES (l_employee_id,l_department_id,l_new_salary);
40       END IF;
41
42     END LOOP emp_loop;
43     CLOSE cur1;
44     /* Print out the changed salaries*/
45     SELECT employee_id,department_id,new_salary from emp_raises
46      ORDER BY employee_id;
47  END;

This is the most complex procedure we have written so far, so let's go through it line by line:

Line(s)

Explanation

1

Create the procedure. It takes a single parameter in_department_id . Since we did not specify the OUT or INOUT mode, the parameter is for input only (that is, the calling program cannot read any changes to the parameter made within the procedure).

4-8

Declare local variables for use within the procedure. The final parameter, done , is given an initial value of 0.

10-13

Create a cursor to retrieve rows from the employees table. Only employees from the department passed in as a parameter to the procedure will be retrieved.

16

Create an error handler to deal with "not found" conditions, so that the program will not terminate with an error after the last row is fetched from the cursor. The handler specifies the CONTINUE clause, so the program execution will continue after the "not found" error is raised. The hander also specifies that the variable done will be set to 1 when this occurs.

18

Create a temporary table to hold a list of rows affected by this procedure. This table, as well as any other temporary tables created in this session, will be dropped automatically when the session terminates.

21

Open our cursor to prepare it to return rows.

22

Create the loop that will execute once for each row returned by the stored procedure. The loop terminates on line 42.

24

Fetch a new row from the cursor into the local variables that were declared earlier in the procedure.

26-28

Declare an IF condition that will execute the LEAVE statement if the variable done is set to 1 (accomplished through the "not found" handler, which means that all rows were fetched).

30

Call the new_salary procedure to calculate the employee's new salary. It takes as its arguments the employee_id and an OUT variable to accept the new salary ( l_new_salary ).

32

Compare the new salary calculated by the procedure called on line 30 with the existing salary returned by the cursor defined on line 10. If they are different, execute the block of code between lines 32 and 40.

34-36

Update the employee salary to the new salary as returned by the new_salary procedure.

38 and 39

Insert a row into our temporary table (defined on line 21) to record the salary adjustment.

43

After all of the rows have been processed , close the cursor.

45

Issue an unbounded SELECT (e.g., one without a WHERE clause) against the temporary table, retrieving the list of employees whose salaries have been updated. Because the SELECT statement is not associated with a cursor or an INTO clause, the rows retrieved will be returned as a result set to the calling program.

47

Terminate the stored procedure.


{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}

When this stored procedure is executed from the MySQL command line with the parameter of department_id set to 18, a list of updated salaries is printed as shown in Example 2-8.

Example 2-8. Output from the "putting it all together" example
mysql> CALL cursor_example2(

18

) //
+-------------+---------------+------------+
 employee_id  department_id  new_salary 
+-------------+---------------+------------+
         396             18    75560.00 
         990             18   118347.00 
+-------------+---------------+------------+
2 rows in set (0.23 sec)

Query OK, 0 rows affected (0.23 sec)