Queries in PSM

• The following rules apply to the use of CS 235: queries: 1. Queries returning a single value can be Introduction to used in assignments 2. Queries returning a single tuple can be used Svetlozar Nestorov with INTO. 3. Queries returning several tuples can be Lecture Notes #15 used via a .

Cursors Fetching Tuples From a Cursor

• A cursor serves as a tuple-variable that • Get next tuple: ranges over the tuples of the result of a FETCH c INTO a1, a2, …, ak; query. – a1, a2, …, ak are the attributes of the result of DECLARE c CURSOR FOR (); the query of c. • Opening a cursor evaluates . – c is moved to the next tuple. OPEN c; • A cursor is used by creating a loop around • Closed with CLOSE c; FETCH.

End of Cursor Cursor Structure

• SQL operations return status in DECLARE c CURSOR FOR… SQLSTATE (in PSM). … • FETCH returns ‘02000’ in SQLSTATE cursorLoop: LOOP … when no more tuples are found. FETCH c INTO…; • Useful declaration: IF NotFound THEN LEAVE cursorLoop; DECLARE NotFound CONDITION FOR END IF; SQLSTATE ‘02000’ … END LOOP;

1 Cursor Example Example

• Write a procedure that makes free all beers BEGIN OPEN c; sold for more than $5 at Spoon. menuLoop: LOOP CREATE PROCEDURE FreeBeer() FETCH c INTO aBeer, aPrice; IF NotFound THEN LEAVE menuLoop END IF; DECLARE aBeer VARCHAR[30]; IF aPrice > 5.00 THEN DECLARE aPrice REAL; UPDATE Sells DECLARE NotFound CONDITION FOR SET price = 0 WHERE bar = ‘Spoon’ and beer = aBeer; SQLSTATE ‘02000’; END IF; DECLARE CURSOR c FOR END LOOP; SELECT beer, price FROM Sells WHERE bar = CLOSE c; ‘Spoon’; END;

MySQL Routines Procedures

• MySQL’s version of PSM (Persistent, CREATE PROCEDURE () Stored Modules). BEGIN – Stored procedures. – Functions. • Brand new feature (in 5.0). END; – Adheres to standards (similar to IBM’s DB2, different Oracle PL/SQL). – Bugs possible (bugs..com)

Functions Arguments

CREATE PROCEDURE () • Argument list has name-mode-type triples. RETURNS – Mode: IN, OUT, or INOUT for read-only, write- BEGIN only, read/write, respectively. – Types: standard SQL. END;

2 Example Declarations

• A procedure to add a beer and price to Spoon’s menu: • Variables DELIMITER // CREATE PROCEDURE addSpoonMenu( • Conditions IN b CHAR(20), •Cursors IN p REAL) BEGIN • Handlers INSERT INTO Sells • Must be declared in this order! VALUES(‘Spoon', b, p); END;// DELIMITER ; CALL addSpoonMenu(‘Guinness’, 7.50);

Conditions Handlers

DECLARE • Define what to do in case of errors (or conditions) CONDITION FOR SQLSTATE DECLARE { EXIT | CONTINUE } DECLARE HANDLER FOR CONDITION FOR { | SQLSTATE | } • The following conditions are predefined: SQL statement – NOT FOUND (no more rows) – SQLEXCEPTION (error) • Common practice: set a flag for CONTINUE handlers and – SQLWARNING (warning) check inside .

Body Constructs Queries in Routines

• Assignments: 1. Single- selects allow retrieval into a SET = – Variables must be declared. variable of the result of a query that is • Branches guaranteed to produce one tuple. IF THEN 2. Cursors allow the retrieval of many ELSE tuples, with the cursor and a loop used to END IF; process each in turn.

3 Cursors in MySQL Example (1/3)

• The cursor declaration is: • The FreeBeer in MySQL: DECLARE CURSOR FOR ; CREATE PROCEDURE FreeBeer() BEGIN • Fetching is done with: DECLARE aBeer CHAR(20); FETCH c INTO ; DECLARE aPrice REAL; DECLARE flag INT DEFAULT 0;

Example (2/3) Example (3/3)

DECLARE menu CURSOR FOR SELECT beer, price OPEN menu; FROM Sells REPEAT FETCH menu INTO aBeer, aPrice; WHERE bar = ‘Spoon’; IF aPrice > 5.00 THEN DECLARE CONTINUE HANDLER UPDATE Sells SET price = 0 FOR NOT FOUND WHERE bar = ‘Spoon’ AND beer = aBeer; SET flag = 1; END IF; UNTIL flag = 1 END REPEAT; CLOSE menu; END;//

4