Week9 DB Stored
Week9 DB Stored
Jianxin Li
(This material will appear in the remaining lab sessions, but will not be on the
final exam.)
Stored Routines
A stored routine is a named set of SQL statements that is stored on the server
and which can be initiated by a single call.
Normally, we imagine the stored routine as being written by the DBA and
called by the client programs.
Stored routines are further subdivided into:
Stored procedures do not return anything
Stored procedures can however assign values to variables etc.
Stored functions that return values to the client
Basic Syntax
The basic syntax for creating the simplest possible procedure, one with no
parameters and consisting of a single SQL statement is as follows:
CREATE PROCEDURE myproc()
/* An SQL statement */
CALL listCapitals();
+-----------------------------+-----------------------------------+
| name | name |
+-----------------------------+-----------------------------------+
| Aruba | Oranjestad |
| Afghanistan | Kabul |
| Angola | Luanda |
| Anguilla | The Valley |
A stored procedure belongs to a specific database, namely the one that was
being used when CREATE PROCEDURE command was issued.
Procedure parameters
In order to do anything more useful than just saving typing, a procedure will
have parameters that the user will specify on calling the procedure
CREATE PROCEDURE listOneCapital(cntry VARCHAR(50))
SELECT C.name, T.name
FROM country C, city T
WHERE C.capital = T.id
AND C.name = cntry;
When the procedure is called the caller specifies an actual value, known as
the argument to the procedure.
CALL listOneCapital(Uganda);
+--------+---------+
| name | name |
+--------+---------+
| Uganda | Kampala |
+--------+---------+
Inside the procedure, the argument in this case Uganda will be used
wherever the variable cntry occurs.
Output Parameters
A procedure has no RETURN statement and doesnt return a value to the caller.
However the caller can specify a user-variable in the parameter list and the
procedure can assign a value to that variable.
CREATE PROCEDURE regionPop(rgn TEXT, OUT rpop INT)
SELECT SUM(population)
FROM country C
WHERE C.region = rgn
INTO rpop;
The output parameter rpop is indicated by the keyword OUT and the SELECT
statement performs the selection INTO the variable.
Nothing appears on the terminal, but the variable @napop has had a value
assigned to it, which can subsequently be used.
SELECT @napop;
+-----------+
| @napop |
+-----------+
| 309632000 |
+-----------+
Multiple statements
END
The solution to this is to temporarily change the delimiter so that we can enter
the entire procedure.
DELIMITER ++
CREATE PROCEDURE myproc()
BEGIN
END++
DELIMITER ;
The first line temporarily changes the delimiter to ++, then the entire
procedure is entered, and finally the delimiter is changed back again.
Procedure Variables
This fragment creates a local variable called rp and then calls the previously
defined procedure to assign the total population of the specified region to that
variable.
1
Henceforth I will not include the DELIMITER statements
Jianxin Li (UWA) Stored routines 13 / 31
Stored Routines
Multiple statements
We can complete this procedure fragment by using the variable that we have
just evaluated in a subsequent SQL statement.
CREATE PROCEDURE regionSummary(rgn TEXT)
BEGIN
DECLARE rp INT;
CALL regionPop(rgn,rp);
SELECT C.name, C.population,
C.population / rp * 100 as perc
FROM country C
WHERE C.region = rgn
ORDER BY C.population
DESC LIMIT 5;
END
This has simply added one more SELECT statement that performs another
query to list the five most populous countries in that region.
Other constructs
Suppose that instead of the top five countries for the specified region, we
wanted to list the most populous and least populous.
We could do this with three SELECT statements one to find the minimum
and maximum country populations in that region, then one each to find which
country has the minimum and the maximum population.
However we could do this with just one SELECT statement provided we
could process the results afterwards.
The algorithm
The algorithm
Always remember the biggest so far, and as each new number comes
along, compare it to the number that is being remembered and update the
remembered number only if the new number is bigger.
A stored procedure
DELIMITER ++
CREATE PROCEDURE regionLimits(rgn TEXT)
BEGIN SET numDone = 1;
Cursors
Cursors are also the primary mechanism by which client programs interact
with the database.
Think of a cursor as a machine that runs a SQL query and returns the results
of this query to you one row at a time as you ask for them.
A cursor springs into existence when execution of the stored procedure
reaches a DECLARE...CURSOR statement it does not run the statement at
this point, but just remembers it.
DECLARE myCursor CURSOR FOR
SELECT year, rate
FROM Investments;
myCursor
At some later stage, when the OPEN statement is executed, the cursor actually
runs the query.
OPEN myCursor;
year rate
myCursor 2007 10.183
2008 -8.954
2009 -11.239
2010 2.110
2011 4.102
2012 5.419
2014 7.451
It does not return the result of the query, but just remembers it.
Jianxin Li (UWA) Stored routines 22 / 31
Programming Routines
The data is extracted from the cursor one row at a time using FETCH.
Each FETCH call causes it to return whichever row it is pointing to
FETCH myCursor INTO a, b;
year rate
2007, 10.183
myCursor 2007 10.183
2008 -8.954
2009 -11.239
2010 2.110
2011 4.102
2012 5.419
2014 7.451
The data is extracted from the cursor one row at a time using FETCH.
Each FETCH call causes it to return whichever row it is pointing to and then
shift the pointer to the next row.
FETCH myCursor INTO a, b;
year rate
myCursor 2007 10.183
2008 -8.954
2009 -11.239
2010 2.110
2011 4.102
2012 5.419
2014 7.451
The data is extracted from the cursor one row at a time using FETCH.
Each FETCH call causes it to return whichever row it is pointing to and then
shift the pointer to the next row.
FETCH myCursor INTO a, b;
year rate
myCursor 2007 10.183
2008 -8.954
2009 -11.239
2010 2.110
2011 4.102
2012 5.419
2014 7.451
year rate
myCursor 2007 10.183
2008 -8.954
2009 -11.239
2010 2.110
2011 4.102
2012 5.419
2014 7.451
CLOSE myCursor; closes the cursor and reclaims the memory and/or other
resources it is using.
Jianxin Li (UWA) Stored routines 24 / 31
Programming Routines
Cursor control
OPEN regionOnly;
CLOSE regionOnly;
END
We will use a loop to process each row, and so we need to know how many
rows the cursor contains; this can be found from the MySQL function
FOUND_ROWS() which returns the number of rows that the last query found.
/* Process a row */
In order to use the cursor to process each row, we need to have variables to
store the name and population of the most populous found so far and least
populous found so far, along with variables for the values extracted from
each row as it is processed.
So the declaration section will need to have the following added to it:
DECLARE minP INT;
DECLARE maxP INT;
DECLARE minC VARCHAR(50);
DECLARE maxC VARCHAR(50);
Initializing
These variables are initialized with the values from the first row (after we have
read just one row, then the name and population are the best-so-far for both
maximum and minimum population.)
SET numDone = 1;
In the loop, we fetch the contents of the next row and compare them to the
existing minimum/maximum values:
WHILE numDone < numRows DO
FETCH regionOnly INTO cname, cpop;
IF (cpop < minP) THEN
SET minP = cpop;
SET minC = cname;
END IF;
IF (cpop > maxP) THEN
SET maxP = cpop;
SET maxC = cname;
END IF;
SET numDone = numDone + 1;
END WHILE;
Finally
Conclusion