MySQL Stored Procedure and
User-Defined Function
http://www.mysqltutorial.org/
ISYS 475
Stored Procedure
• A stored procedure is a program with SQL
code which is stored in the database catalog
and can be invoked later by a program, a
trigger or even a stored procedure.
• MySQL supports stored procedure since
version 5.0 to allow MySQL more flexible
and powerful.
Three Ways to Create A Procedure
• 1. Save the procedure commands in a text
file.
• 2. Use the phpMyAdmin utility to enter
commands
– Routine/Add routine
• 3. Enter the commands using the MySQL
command prompt.
Example of a command file
DELIMITER //
CREATE PROCEDURE Hello()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
SELECT 'Hello World !';
END
//
phpMyAdmin: Routines/Add
routine interface
Optional characteristics
• Type: Procedure/Function
• Language :the default value is SQL.
• Deterministic : If the procedure always returns the
same results, given the same input. The default
value is NOT DETERMINISTIC.
• SQL Security : At call time, check privileges of the
user. INVOKER is the user who calls the
procedure. DEFINER is the creator of the
procedure. The default value is DEFINER.
• Comment : For documentation purposes; the
default value is ""
Run a procedure
• With phpMyAdmin:
– Routines/select the procedure and click execute
• With the command prompt:
CALL stored_procedure_name (param1, param2, ....);
CREATE PROCEDURE ProcName()
• Stored procedure names are case insensitive
• A procedure may have parameters
Define parameters within a stored procedure
• Parameter list is empty
– CREATE PROCEDURE proc1 () :
• Define input parameter with key word IN:
– CREATE PROCEDURE proc1 (IN varname DATATYPE)
– The word IN is optional because parameters are IN (input)
by default.
• Define output parameter with OUT:
– CREATE PROCEDURE proc1 (OUT varname DATATYPE)
• A procedure may have input and output paramters:
– CREATE PROCEDURE proc1 (INOUT varname DATATYPE)
Executable Section
• BEGIN
Statements
• END
Examples of parameters
CREATE PROCEDURE proc_IN (IN var1 INT)
BEGIN
SELECT var1 + 2 AS result;
END
CREATE PROCEDURE proc_OUT(OUT var1 VARCHAR(100))
BEGIN
SET var1 = 'This is a test';
END
CREATE PROCEDURE proc_INOUT (IN var1 INT,OUT var2
INT)
BEGIN
SET var2 = var1 * 2;
END
Variable Declaration
• DECLARE variable_name datatype(size) DEFAULT default_value;
• Variable naming rules: Identifiers can consist of any
alphanumeric characters, plus the characters '_' and '$'.
Identifiers can start with any character that is legal in an
identifier, including a digit. However, an identifier cannot
consist entirely of digits.
• Data types:A variable can have any MySQL data
types. For example:
– Character: CHAR(n), VARCHAR(n)
– Number: INT, SMALLINT, DECIMAL(i,j), DOUBLE
– Date: DATE, TIME, DATETIME
– BOOLEAN
• http://www.mysqltutorial.org/mysql-data-types.aspx
Examples
DECLARE x, y INT DEFAULT 0;
DECLARE today TIMESTAMP DEFAULT CURRENT_DATE;
DECLARE ename VARCHAR(50);
DECLARE no_more_rows BOOLEAN;
SET no_more_rows = TRUE;
Assigning variables
• Using the SET command:
DECLARE total_count INT DEFAULT 0;
SET total_count = 10;
Using the SELECT INTO command:
DECLARE total_products INT DEFAULT 0;
SELECT COUNT(*) INTO total_products
FROM products;
SELECT … INTO
•
•
•
•
•
SELECT columns separated by commas
INTO variables separated by commas
FROM tablename
WHERE condition;
Ex:
– SELECT cid, cname INTO custID, customername
– FROM customer
– WHERE cid = ‘c01’;
Arithmetic and string operators
• Arithmetic operators:
+, -, *, /
• Modulo operator:
– % or mod
• Other math calculations use math functions:
– Pow(x,y)
• Concatenation uses CONCAT function:
– SELECT CONCAT('New ', 'York ', 'City');
MySQL Comparison Operators
•
•
•
•
•
•
•
EQUAL(=)
LESS THAN(<)
LESS THAN OR EQUAL(<=)
GREATER THAN(>)
GREATER THAN OR EQUAL(>=)
NOT EQUAL(<>,!=)
Logical Operators
• Logical AND:
– AND, &&
– UnitsInStock < ReorderLevel AND CategoryID=1
– UnitsInStock < ReorderLevel && CategoryID=1
• Negates value:
– NOT, !
• Logical OR:
– ||, OR
– CategoryID=1 OR CategoryID=8
– CategoryID=1 || CategoryID=8
IF statement: The IF statement can have
THEN, ELSE, and ELSEIF clauses, and it is
terminated with END IF.
IF variable1 = 0 THEN
SELECT variable1;
END IF;
IF param1 = 0 THEN
SELECT 'Parameter value = 0';
ELSE
SELECT 'Parameter value <> 0';
END IF;
CASE Statement
CREATE PROCEDURE proc_CASE(IN param1 INT)
BEGIN
DECLARE variable1 INT;
SET variable1 = param1 + 1;
CASE variable1
WHEN 0 THEN
INSERT INTO table1 VALUES (param1);
WHEN 1 THEN
INSERT INTO table1 VALUES (variable1);
ELSE
INSERT INTO table1 VALUES (99);
END CASE;
END
WHILE cond DO statement
CREATE PROCEDURE proc_WHILE (IN param1 INT)
BEGIN
DECLARE variable1, variable2 INT;
SET variable1 = 0;
WHILE variable1 < param1 DO
INSERT INTO table1 VALUES (param1);
SELECT COUNT(*) INTO variable2 FROM table1;
SET variable1 = variable2;
END WHILE;
END
Comment Syntax
• From a /* sequence to the following */
sequence.
• From a “#” character to the end of the line.
• From a “-- ” sequence to the end of the line.
In MySQL, the “-- ” (double-dash) comment
style requires the second dash to be followed
by at least one whitespace
-- Programmer: John Smith
A Procedure to compute tax that takes sidIN and taxRate
as inputs and return taxOut as output
DELIMITER //
CREATE PROCEDURE Caltax(sidIN char(5), taxRate double, out taxOut
double)
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
DECLARE tax DOUBLE;
DECLARE empSalary DOUBLE;
select Salary into empSalary from salesreps where sid = sidIN;
set taxOut=taxRate*empSalary;
END
//
• Note 1: No need to surround the sidIN with
quotation mark:
select Salary into empSalary from salesreps
where sid = sidIN;
• Note 2: The delimiter is changed to // to
enable the entire definition to be passed to
the server as a single statement. It can be
restored to “;” mysql>delimiter ;
User-Defined Temporary Variables
• User variables are written as @var_name.
mysql> SET @t1=1, @t2=2, @t3:=4;
mysql> SELECT @t1, @t2, @t3, @t4 := @t1+@t2+@t3;
+------+------+------+--------------------+
| @t1 | @t2 | @t3 | @t4 := @t1+@t2+@t3 |
+------+------+------+--------------------+
| 1| 2| 4|
7|
+------+------+------+--------------------+
Example of running the procedure from
the command prompt
mysql> delimiter ;
mysql> set @tax=0;
Query OK, 0 rows affected (0.00 sec)
mysql> call caltax('S1',0.1,@tax);
Query OK, 1 row affected (0.00 sec)
mysql> select @tax;
+------+
| @tax |
+------+
| 650 |
+------+
1 row in set (0.00 sec)
First, check if the customer exist before adding a new order
DELIMITER //
CREATE PROCEDURE addOrder(oidIN char(5), cidIN char(5), sidIN char(5), odateIN date)
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
DECLARE cidTemp char(5) default "x";
select cid into cidTemp from customers where cid = cidIN;
IF cidTemp=cidIN THEN
insert into orders values(oidIN,cidIN,sidIN,odateIN);
END IF;
END
//
mysql> call addOrder('O8','C12','S1','2013-06-10');
Query OK, 0 rows affected, 1 warning (0.00 sec) because C12 not exist!
Using Routines/Execute
Example:Procedure showCustomers
DELIMITER //
DROP PROCEDURE IF EXISTS showCustomers;
CREATE PROCEDURE showCustomers ()
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
Select * from Customers;
END
//
DELIMITER ;
Using PDO Calling a stored procedure with a SQL
Select statement: select * from customers
<?php
$dsn = 'mysql:host=localhost;dbname=salesdb';
$username = 'root';
$password = '';
$db = new PDO($dsn, $username, $password);
$customers= $db->query('CALL showCustomers()');
echo "<table border=1><tr>" . "<th>CID</th>" . "<th>CName</th>" .
"<th>City</th>" . "<th>Rating</th></tr>";
foreach ($customers as $customer){
$cid=$customer["cid"]; //field name is case sensitive
$Cname=$customer["cname"];
$City=$customer["city"];
$Rating=$customer["rating"];
echo "<tr><td>$cid</td>" . "<td>$Cname</td>" . "<td>$City</td>" .
"<td>$Rating</td></tr>";
}
?>
Calling a procedure with OUT
parameter
• Must use MySQL temporary @variable to
receive the output value.
• Because a stored procedure does not return
to PHP anything, it returns the value into
the MySQL variable (@return) (scope is in
MySQL), so you need to query this variable
in a separate call.
Example Using PDO
<?php
$sid=$_POST["empID"];
$taxRate=$_POST["taxRate"];
$dsn = 'mysql:host=localhost;dbname=salesdb';
$username = 'root';
$password = '';
$db = new PDO($dsn, $username, $password);
$db->query("SET @tax=''");
$myquery="call Caltax('" . $sid . "'," . $taxRate . ",@tax)";
echo $myquery;
$db->query( $myquery );
$rs = $db->query( 'SELECT @tax;');
// $row = $rs->fetch(PDO::FETCH_NUM);
foreach ($rs as $row){
echo "<p>SID: $sid </P>";
echo "<p>Rate: $taxRate </P>";
echo "<p>Tax: $row[0] </P>";
} ?>
A few notes
• 1. We need to create a MySQL variable using the
SET command:
$db->query("SET @tax=''");
• 2. Passing PHP variables as inputs will not work.
This statement does not work:
– $db->query( "call Caltax($sid, $taxRate,@tax);" );
• 3. We need to create a string for the Call
statement. String input must be quoted:
– $myquery="call Caltax('" . $sid . "'," . $taxRate . ",@tax)";
– $db->query( $myquery );
• 4. Then runs a Select command to read the output
variables:
– $rs = $db->query( 'SELECT @tax;');
Triggers
• A trigger is a program stored in the database and is
called automatically when a triggering event occurs.
• It is associated with a table, and that activates when
a particular event occurs for the table. Some uses for
triggers are to perform checks of values to be
inserted into a table or to perform calculations on
values involved in an update.
• A trigger is defined to activate when an INSERT,
DELETE, or UPDATE statement executes for the
associated table. A trigger can be set to activate
either before or after the triggering statement.
CREATE TRIGGER Syntax
CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_body
• trigger_time: It can be BEFORE or AFTER
• trigger_event: Insert, Delete, Update
• Example:
CREATE TRIGGER ratingChanged AFTER
UPDATE ON customers
FOR EACH ROW
OLD and NEW
• You can refer to columns in the subject
table (the table associated with the trigger)
by using the aliases OLD and NEW.
OLD.col_name refers to a column of an
existing row before it is updated or deleted.
NEW.col_name refers to the column of a
new row to be inserted or an existing row
after it is updated.
Example: Customer Rating
Change Log
• Table name: CustomerLog
• Fields: CID, Cname, OldRating,NewRating
Demo :New and :Old
delimiter //
DROP TRIGGER IF EXISTS ratingChanged;
CREATE TRIGGER ratingChanged AFTER UPDATE ON customers
FOR EACH ROW
BEGIN
insert into customerlog values(old.cid,old.cname,old.rating,new.rating);
END
//
delimiter ;
Example
mysql> update customers set rating='c' where cid='C1';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from customerlog;
+-----+-------+-----------+-----------+
| cid | Cname | OldRating | NewRating |
+-----+-------+-----------+-----------+
| C1 | MYERS | A
|c
|
+-----+-------+-----------+-----------+
1 row in set (0.00 sec)
Updating the onhand quantity after a new detail line is added:
delimiter //
DROP TRIGGER IF EXISTS adddetail;
CREATE TRIGGER adddetail AFTER INSERT ON odetails
FOR EACH ROW
BEGIN
DECLARE stocks decimal(5,1);
select onhand into stocks from products where pid=new.pid;
update products set onhand=onhand - new.qty where pid=new.pid;
END
//
delimiter ;
Example
mysql> select * from products;
+------+---------------+--------+--------+
| pid | pname
| price | onhand |
+------+---------------+--------+--------+
| P1 | COMPUTER
| 850.00 | 50.0 |
| P2 | SVGA MONITOR | 300.00 | 25.0 |
| P3 | LASER PRINTER | 530.00 | 10.0 |
| P4 | HARD DRIVE | 125.00 | 40.0 |
| P5 | SERIAL MOUSE | 25.00 | 75.0 |
| P6 | TAPE BACKUP | 225.00 | 15.0 |
| P7 | TRACKBALL | 15.00 | 55.0 |
+------+---------------+--------+--------+
mysql> insert into odetails values('O6','P2',5);
Query OK, 1 row affected (0.03 sec)
mysql> select * from products;
+------+---------------+--------+--------+
| pid | pname
| price | onhand |
+------+---------------+--------+--------+
| P1 | COMPUTER
| 850.00 | 50.0 |
| P2 | SVGA MONITOR | 300.00 | 20.0 |
| P3 | LASER PRINTER | 530.00 | 10.0 |
| P4 | HARD DRIVE | 125.00 | 40.0 |
| P5 | SERIAL MOUSE | 25.00 | 75.0 |
| P6 | TAPE BACKUP | 225.00 | 15.0 |
| P7 | TRACKBALL | 15.00 | 55.0 |
+------+---------------+--------+--------+
User Defined Functions
• Stored functions differ from stored
procedures in that stored functions actually
return a value.
• Stored functions have only input parameters
(if any parameters at all), so the IN , OUT ,
and INOUT keywords aren’t used.
• Stored functions have no output parameters;
instead, you use a RETURN statement to
return a value whose type is determined by
the RETURNS type statement, which
precedes the body of the function.
Example
DELIMITER //
DROP FUNCTION IF EXISTS empTax;
CREATE FUNCTION empTax(Salary Decimal(10,2)) RETURNS
Decimal(10,2)
BEGIN
Declare tax decimal(10,2);
if salary < 3000.00 then
set tax=salary*0.1;
elseif Salary <5000.00 then
set tax=Salary*0.2;
else
set tax=Salary*0.3;
end if;
return tax;
END
//
Using the User-defined Function
with SQL
mysql> delimiter ;
mysql> select sname, emptax(Salary) as tax from salesreps;
+-------+---------+
| sname | tax |
+-------+---------+
| PETER | 1950.00 |
| PAUL | 2160.00 |
| MARY | 2250.00 |
+-------+---------+
3 rows in set (0.00 sec)
Example of Using a User-Defined Function
<?php
$db = new mysqli('localhost','root','','salesdb');
$rs=$db->query( 'select sname, emptax(Salary) as tax from salesreps' );
echo "<table border=1><tr>" . "<th>Sname</th>" . "<th>Tax</th></tr>";
foreach ($rs as $row){
$sname=$row["sname"]; //field name is case sensitive
$tax=$row["tax"];
echo "<tr><td>$sname</td>" . "<td>$tax</td></tr>";
}
?>
Cursors
• A cursor is a pointer to a set of records
returned by a SQL statement. It enables
you to take a set of records and deal with it
on a row-by-row basis.
Cursor has three important
properties
• The cursor will not reflect changes in its
source tables.
• Read Only : Cursors are not updatable.
• Not Scrollable : Cursors can be traversed
only in one direction, forward, and you can't
skip records from fetching.
Defining and Using Cursors
• Declare cursor:
– DECLARE cursor-name CURSOR FOR SELECT ...;
• DECLARE CONTINUE HANDLER FOR NOT FOUND:
Specify what to do when no more records found
– DECLARE b INT;
– DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1;
Open cursor:
OPEN cursor-name;
Fetch data into variables:
FETCH cursor-name INTO variable [, variable];
CLOSE cursor:
CLOSE cursor-name;
Cursor Example
DELIMITER //
DROP Procedure IF EXISTS maleSum;
CREATE Procedure maleSum(OUT sumSalary Decimal(10,2))
BEGIN
DECLARE Sal,sumSal decimal(10,2);
DECLARE continueFlag int default 0;
DECLARE maleCursor CURSOR FOR SELECT Salary FROM salesreps where sex='M';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET continueFlag = 1;
OPEN maleCursor;
SET Sal = 0;
SET sumSal= 0;
WHILE continueFlag = 0 DO
FETCH maleCursor INTO Sal;
IF continueFlag = 0 THEN
SET sumSal = sumSal+Sal;
END IF;
END WHILE;
CLOSE maleCursor;
SET sumSalary=sumSal;
END
//
A procedure to create email list using cursor
DELIMITER //
DROP PROCEDURE IF EXISTS emailgroup;
CREATE PROCEDURE emailgroup (INOUT emaillist varchar(4000))
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure'
BEGIN
DECLARE continueFlag INTEGER DEFAULT 0;
DECLARE useremail varchar(100) DEFAULT "";
DEClARE email_cursor CURSOR FOR SELECT email FROM users;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET continueFlag = 1;
OPEN email_cursor;
WHILE continueFlag = 0 DO
FETCH email_cursor INTO useremail;
IF continueFlag = 0 THEN
SET emaillist = CONCAT(useremail,";",emaillist);
END IF;
END WHILE;
CLOSE email_cursor;
END
//
DELIMITER ;
© Copyright 2026 Paperzz