SQL/PSM Stored Procedures Basic PSM Form Parameters In
Total Page:16
File Type:pdf, Size:1020Kb
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 <name> ( Unlike the usual name-type pairs in <parameter list> ) languages like C, PSM uses mode- <optional local declarations> name-type triples, where the mode can be: <body>; IN = procedure uses value, does not Function alternative: change value. CREATE FUNCTION <name> ( OUT = procedure changes, does not use. <parameter list> ) RETURNS <type> INOUT = both. 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 <expression> sets the return name of the desired procedure and value of a function. arguments. Unlike C, etc., RETURN does not terminate Example: function execution. CALL JoeMenu(’Moosedrool’, 5.00); DECLARE <name> <type> used to declare local variables. Functions used in SQL expressions wherever a value of their return type is appropriate. BEGIN . END for groups of statements. Separate statements by semicolons. 7 8 2 Types of PSM Statements --- (2) IF Statements Assignment statements: Simplest form: SET <variable> = <expression>; IF <condition> THEN Example: SET b = ’Bud’; <statements(s)> END IF; Statement labels: give a statement a Add ELSE <statement(s)> if desired, as label by prefixing a name and a colon. IF . THEN . ELSE . END IF; Add additional cases by ELSEIF <statements(s)>: IF … THEN … ELSEIF … ELSEIF … ELSE … END IF; 9 10 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 <statements> END LOOP; . Exit from a loop by: LEAVE loop1; If this statement is executed . LEAVE <loop name> . The <loop name> is associated with a END LOOP; loop by prepending the name and a Control winds up here colon to the keyword LOOP. 13 14 Other Loop Forms Queries WHILE <condition> General SELECT-FROM-WHERE DO <statements> queries are not permitted in PSM. END WHILE; There are three ways to get the effect REPEAT <statements> of a query: UNTIL <condition> 1. Queries producing one value can be the END REPEAT; expression in an assignment. 2. Single-row SELECT . INTO. 3. Cursors. 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 <variable> after the SELECT clause. SET p = (SELECT price FROM Sells Example: WHERE bar = ’Joe’’s Bar’ AND SELECT price INTO p FROM Sells beer = ’Bud’); WHERE bar = ’Joe’’s Bar’ AND beer = ’Bud’; 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 <query>; to point to the first tuple of the result. When finished with c, issue command: CLOSE c; 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.