Stored Procedures
PSM, or “persistent, stored modules,” SQL/PSM allows us to store procedures as database schema elements. PSM = a mixture of conventional Procedures Stored in the Database statements (if, while, etc.) and SQL. General-Purpose Programming Lets us do things we cannot do in SQL alone.
1 2
Basic PSM Form Parameters in PSM
CREATE PROCEDURE
3 4
1 Example: Stored Procedure The Procedure
Let’s write a procedure that takes two CREATE PROCEDURE JoeMenu ( arguments b and p, and adds a tuple IN b CHAR(20), Parameters are both to Sells(bar, beer, price) that has bar = IN p REAL read-only, not changed ’Joe’’s Bar’, beer = b, and price = p. ) Used by Joe to add to his menu more easily. INSERT INTO Sells The body --- VALUES(’Joe’’s Bar’, b, p); a single insertion
5 6
Invoking Procedures Types of PSM statements --- (1)
Use SQL/PSM statement CALL, with the RETURN
7 8
2 Types of PSM Statements --- (2) IF Statements
Assignment statements: Simplest form: SET
Example: IF Example: IF (continued)
CREATE FUNCTION Rate (IN b CHAR(20) ) Let’s rate bars by how many customers Number of RETURNS CHAR(10) customers of they have, based on Frequents(drinker,bar). DECLARE cust INTEGER; bar b <100 customers: ‘unpopular’. BEGIN 100-199 customers: ‘average’. SET cust = (SELECT COUNT(*) FROM Frequents >= 200 customers: ‘popular’. WHERE bar = b); IF cust < 100 THEN RETURN ’unpopular’ Function Rate(b) rates bar b. ELSEIF cust < 200 THEN RETURN ’average’ ELSE RETURN ’popular’ END IF; Nested IF statement 11 END; Return occurs here, not at 12 one of the RETURN statements
3 Loops Example: Exiting a Loop
Basic form: loop1: LOOP LOOP
loop by prepending the name and a Control winds up here colon to the keyword LOOP.
13 14
Other Loop Forms Queries
WHILE
15 16
4 Example: Assignment/Query SELECT . . . INTO
If p is a local variable and Sells(bar, beer, An equivalent way to get the value of a query price) the usual relation, we can get the price that is guaranteed to return one tuple is by Joe charges for Bud by: placing INTO
17 18
Cursors Opening and Closing Cursors
A cursor is essentially a tuple-variable To use cursor c, we must issue the that ranges over all tuples in the result command: of some query. OPEN c; Declare a cursor c by: The query of c is evaluated, and c is set DECLARE c CURSOR FOR
19 20
5 Fetching Tuples From a Cursor Breaking Cursor Loops --- (1)
To get the next tuple from cursor c, The usual way to use a cursor is to issue command: create a loop with a FETCH statement, FETCH FROM c INTO x1, x2,…,xn ; and do something with each tuple The x ’s are a list of variables, one for fetched. each component of the tuples referred A tricky point is how we get out of the to by c. loop when the cursor has no more c is moved automatically to the next tuples to deliver. tuple. 21 22
Breaking Cursor Loops --- (2) Breaking Cursor Loops --- (3)
Each SQL operation returns a status, We may declare a condition, which is a which is a 5-digit number. boolean variable that is true if and only For example, 00000 = “Everything OK,” if SQLSTATE has a particular value. and 02000 = “Failed to find a tuple.” Example: We can declare condition In PSM, we can get the value of the NotFound to represent 02000 by: status in a variable called SQLSTATE. DECLARE NotFound CONDITION FOR SQLSTATE ’02000’;
23 24
6 Breaking Cursor Loops --- (4) Example: Cursor
The structure of a cursor loop is thus: Let’s write a procedure that examines cursorLoop: LOOP Sells(bar, beer, price), and raises by $1 … the price of all beers at Joe’s Bar that FETCH c INTO … ; are under $3. IF NotFound THEN LEAVE cursorLoop; Yes, we could write this as a simple END IF; UPDATE, but the details are instructive anyway. … END LOOP;
25 26
The Procedure Body The Needed Declarations BEGIN OPEN c; Check if the recent FETCH failed to CREATE PROCEDURE JoeGouge( ) Used to hold menuLoop: LOOP get a tuple DECLARE theBeer CHAR(20); beer-price pairs FETCH c INTO theBeer, thePrice; when fetching DECLARE thePrice REAL; through cursor c IF NotFound THEN LEAVE menuLoop END IF; DECLARE NotFound CONDITION FOR IF thePrice < 3.00 THEN UPDATE Sells SET price = thePrice + 1.00 SQLSTATE ’02000’; WHERE bar = ’Joe’’s Bar’ AND beer = theBeer; Returns Joe’s menu DECLARE c CURSOR FOR END IF; END LOOP; (SELECT beer, price FROM Sells If Joe charges less than $3 for WHERE bar = ’Joe’’s Bar’); CLOSE c; the beer, raise it’s price at END; Joe’s Bar by $1. 27 28
7