Stored Procedure 1
Stored Procedure 1
1. Reduce network traffic. Stored procedures help reduce the network traffic between
applications and MySQL Server. Because instead of sending multiple lengthy SQL
statements, applications have to send only the name and parameters of stored
procedures.
2. Centralize business logic in the database. You can use the stored procedures to
implement business logic that is reusable by multiple applications. The stored
procedures help reduce the efforts of duplicating the same logic in many applications
and make your database more consistent.
3. Make database more secure. The database administrator can grant appropriate
privileges to applications that only access specific stored procedures without giving any
privileges on the underlying tables.
1. Resource usages. If you use many stored procedures, the memory usage of every
connection will increase substantially. Besides, overusing a large number of logical
operations in the stored procedures will increase the CPU usage because the MySQL is
not well-designed for logical operations.
2. Troubleshooting. It’s difficult to debug stored procedures. Unfortunately, MySQL does
not provide any facilities to debug stored procedures like other enterprise database
products such as Oracle and SQL Server.
This query returns all products in the products table from the sample database.
The following statement creates a new stored procedure that wraps the query:
DELIMITER //
DELIMITER ;
The first and last DELIMITER commands are not a part of the stored procedure. The
first DELIMITER command changes the default delimiter to // and the last DELIMITER command
changes the delimiter back to the default one which is semicolon (;).
To create a new stored procedure, you use the CREATE PROCEDURE statement.
• First, specify the name of the stored procedure that you want to create after
the CREATE PROCEDURE keywords.
• Second, specify a list of comma-separated parameters for the stored procedure in
parentheses after the procedure name. Note that you’ll learn how to create stored
procedures with parameters in the upcoming tutorials.
• Third, write the code between the BEGIN END block. The above example just has a
simple SELECT statement. After the END keyword, you place the delimiter character to
end the procedure statement.
CALL stored_procedure_name(argument_list);
In this syntax, you specify the name of the stored procedure after the CALL keyword. If the
stored procedure has parameters, you need to pass arguments inside parentheses following
the stored procedure name.
CALL GetAllProducts();
Often, stored procedures have parameters. The parameters make the stored procedure more
useful and reusable. A parameter in a stored procedure has one of three
modes: IN,OUT, or INOUT.
IN parameters
IN is the default mode. When you define an IN parameter in a stored procedure, the calling
program has to pass an argument to the stored procedure.
In addition, the value of an IN parameter is protected. It means that even you change the value
of the IN parameter inside the stored procedure, its original value is unchanged after the stored
procedure ends. In other words, the stored procedure only works on the copy of
the IN parameter.
OUT parameters
The value of an OUT parameter can be changed inside the stored procedure and its new value is
passed back to the calling program.
Notice that the stored procedure cannot access the initial value of the OUT parameter when it
starts.
INOUT parameters
An INOUT parameter is a combination of IN and OUT parameters. It means that the calling
program may pass the argument, and the stored procedure can modify the INOUT parameter,
and pass the new value back to the calling program.
Defining a parameter
In this syntax,
• First, specify the parameter mode, which can be IN , OUT or INOUT depending on the
purpose of the parameter in the stored procedure.
• Second, specify the name of the parameter. The parameter name must follow the
naming rules of the column name in MySQL.
• Third, specify the data type and maximum length of the parameter.
The following example creates a stored procedure that finds all offices that locate in a country
specified by the input parameter countryName:
DELIMITER //
DELIMITER ;
Suppose that you want to find offices locating in the USA, you need to pass an argument (USA)
to the stored procedure as shown in the following query:
CALL GetOfficeByCountry('USA');
To find offices in France, you pass the literal string France to the GetOfficeByCountry stored
procedure as follows:
CALL GetOfficeByCountry('France')
Because the countryName is the IN parameter, you must pass an argument. If you don’t do so,
you’ll get an error:
CALL GetOfficeByCountry();
The following stored procedure returns the number of orders by order status.
DELIMITER $$
DELIMITER ;
CALL GetOrderCountByStatus('Shipped',@total);
SELECT @total;
To get the number of orders that are in-process, you call the stored
procedure GetOrderCountByStatus as follows:
The following example demonstrates how to use an INOUT parameter in a stored procedure:
DELIMITER $$
DELIMITER ;
In this example, the stored procedure SetCounter() accepts one INOUT parameter ( counter )
and one IN parameter ( inc ). It increases the counter ( counter ) by the value of specified by
the inc parameter.
SET @counter = 1;
CALL SetCounter(@counter,1); -- 2
CALL SetCounter(@counter,1); -- 3
CALL SetCounter(@counter,5); -- 8
SELECT @counter; -- 8
A variable is a named data object whose value can change during the stored
procedure execution. You typically use variables in stored procedures to hold immediate
results. These variables are local to the stored procedure.
Declaring variables
To declare a variable inside a stored procedure, you use the DECLARE statement as follows:
In this syntax:
• First, specify the name of the variable after the DECLARE keyword. The variable name
must follow the naming rules of MySQL table column names.
• Second, specify the data type and length of the variable. A variable can have any MySQL
data types such as INT, VARCHAR , and DATETIME.
• Third, assign a variable a default value using the DEFAULT option. If you declare a
variable without specifying a default value, its value is NULL.
The following example declares a variable named totalSale with the data type DEC(10,2) and
default value 0.0 as follows:
MySQL allows you to declare two or more variables that share the same data type using a
single DECLARE statement. The following example declares two integer variables x and y, and
set their default values to zero.
Once a variable is declared, it is ready to use. To assign a variable a value, you use
the SET statement:
For example:
In addition to the SET statement, you can use the SELECT INTO statement to assign the result of
a query to a variable as shown in the following example:
SELECT COUNT(*)
INTO productCount
FROM products;
In this example:
Variable scopes
A variable has its own scope that defines its lifetime. If you declare a variable inside a stored
procedure, it will be out of scope when the END statement of stored procedure reaches.
When you declare a variable inside the block BEGIN END, it will be out of scope if the END is
reached.
MySQL allows you to declare two or more variables that share the same name in different
scopes. Because a variable is only effective in its scope. However, declaring variables with the
same name in different scopes is not good programming practice.
A variable whose name begins with the @ sign is a session variable. It is available and accessible
until the session ends.
Putting it all together
The following example illustrates how to declare and use a variable in a stored procedure:
DELIMITER //
SELECT COUNT(*)
INTO totalOrder
FROM orders;
SELECT totalOrder;
END //
DELIMITER ;
How it works.
First, declare a variable totalOrder with a default value of zero. This variable will hold the
number of orders from the orders table.
Second, use the SELECT INTO statement to assign the variable totalOrder the number of orders
selected from the orders table:
SELECT COUNT(*)
INTO totalOrder
FROM orders;
SELECT totalOrder;
CALL GetTotalOrder();
The SHOW PROCEDURE STATUS statement shows all characteristic of stored procedures
including stored procedure names. It returns stored procedures that you have a privilege to
access.
The following statement shows all stored procedure in the current MySQL server:
If you just want to show stored procedures in a particular database, you can use
a WHERE clause in the SHOW PROCEDURE STATUS as shown in the following statement:
For example, this statement lists all stored procedures in the sample database classicmodels:
In case you want to find stored procedures whose names contain a specific word, you can use
the LIKE clause as follows:
The following statement shows all stored procedure whose names contain the wordOrder:
The IF statement has three forms: simple IF-THEN statement, IF-THEN-ELSE statement, and IF-
THEN-ELSEIF- ELSE statement.
The IF-THEN statement allows you to execute a set of SQL statements based on a specified
condition. The following illustrates the syntax of the IF-THEN statement:
IF condition THEN
statements;
END IF;
In this syntax:
• First, specify a condition to execute the code between the IF-THEN and END IF . If
the condition evaluates to TRUE, the statements between IF-THEN and END IF will execute.
Otherwise, the control is passed to the next statement following the END IF.
• Second, specify the code that will execute if the condition evaluates to TRUE.
We’ll use the customers table from the sample database for the demonstration:
See the following GetCustomerLevel() stored procedure.
DELIMITER $$
SELECT creditLimit
INTO credit
FROM customers
WHERE customerNumber = pCustomerNumber;
DELIMITER ;
This statement finds all customers that have a credit limit greater than 50,000:
SELECT
customerNumber,
creditLimit
FROM
customers
WHERE
creditLimit > 50000
ORDER BY
creditLimit DESC;
These statements call the GetCustomerLevel() stored procedure for customer 141 and show the
value of the OUT parameter pCustomerLevel:
Because the customer 141 has a credit limit greater than 50,000, its level is set to PLATINUM as
expected.
In case you want to execute other statements when the condition in the IF branch does not
evaluate to TRUE, you can use the IF-THEN-ELSE statement as follows:
IF condition THEN
statements;
ELSE
else-statements;
END IF;
In this syntax, if the condition evaluates to TRUE, the statements between IF-
THEN and ELSE execute. Otherwise, the else-statements between the ELSE and END IF execute.
Then, create the GetCustomerLevel() stored procedure with the new code:
DELIMITER //
SELECT creditLimit
INTO credit
FROM customers
WHERE customerNumber = pCustomerNumber;
DELIMITER ;
In this new stored procedure, we include the ELSE branch. If the credit is not greater
than 50,000, we set the customer level to NOT PLATINUM in the block between ELSE and END
IF.
This query finds customers that have credit limit less than or equal 50,000:
SELECT
customerNumber,
creditLimit
FROM
customers
WHERE
creditLimit <= 50000
ORDER BY
creditLimit DESC;
This picture shows the partial output:
The following statements call the stored procedure for customer number 447 and show the
value of the OUT parameter pCustomerLevel:
The credit limit of the customer 447 is less than 50,000, therefore, the statement in
the ELSE branch executes and sets the value of the OUT parameter pCustomerLevel to NOT
PLATINUM.
If you want to execute statements conditionally based on multiple conditions, you use the
following IF-THEN-ELSEIF-ELSE statement:
IF condition THEN
statements;
ELSEIF elseif-condition THEN
elseif-statements;
...
ELSE
else-statements;
END IF;
In this syntax, if the condition evaluates to TRUE , the statements in the IF-THEN branch
executes; otherwise, the next elseif-condition is evaluated.
If no condition in the IF and ELSE IF evaluates to TRUE, the else-statements in the ELSE branch
will execute.
Then, create the new GetCustomerLevel() stored procedure that uses the the IF-THEN-ELSEIF-
ELSE statement.
DELIMITER $$
SELECT creditLimit
INTO credit
FROM customers
WHERE customerNumber = pCustomerNumber;
DELIMITER ;
• If the credit is greater than 50,000, the level of the customer is PLATINUM.
• If the credit is less than or equal 50,000 and greater than 10,000, then the level of
customer is GOLD.
• Otherwise, the level of the customer is SILVER.
These statements call the stored procedure GetCustomerLevel() and show the level of the
customer 447:
CALL GetCustomerLevel(447, @level);
SELECT @level;
If you test the stored procedure with the customer that has a credit limit of 10000 or less, you
will get the output as SILVER.
The CASE statement has two forms: simpleCASE and searched CASE statements.
Note that if you want to add the if-else logic to an SQL statement, you use
the CASE expression which is different from the CASE statement described in this tutorial.
CASE case_value
WHEN when_value1 THEN statements
WHEN when_value2 THEN statements
...
[ELSE else-statements]
END CASE;
In this syntax, the simple CASE statement sequentially compares the case_value is with
the when_value1, when_value2, … until it finds one is equal. When the CASE finds
a case_value equal to a when_value, it executes statements in the corresponding THEN clause.
If CASE cannot find any when_value equal to the case_value, it executes the else-statements in
the ELSE clause if the ELSE clause is available.
When the ELSE clause does not exist and the CASE cannot find any when_value equal to
the case_value, it issues an error:
To avoid the error when the case_value does not equal any when_value, you can use an
empty BEGIN END block in the ELSE clause as follows:
CASE case_value
WHEN when_value1 THEN ...
WHEN when_value2 THEN ...
ELSE
BEGIN
END;
END CASE;
The simple CASE statement tests for equality ( =), you cannot use it to test equality with NULL;
because NULL = NULL returns FALSE.
The following stored procedure illustrates how to use the simple CASE statement:
DELIMITER $$
SELECT
country
INTO customerCountry FROM
customers
WHERE
customerNumber = pCustomerNUmber;
CASE customerCountry
WHEN 'USA' THEN
SET pShipping = '2-day Shipping';
WHEN 'Canada' THEN
SET pShipping = '3-day Shipping';
ELSE
SET pShipping = '5-day Shipping';
END CASE;
END$$
DELIMITER ;
How it works.
The GetCustomerShipping() stored procedure accepts two parameters: pCustomerNumber as
an IN parameter and pShipping as an OUT parameter.
First, select the country of the customer from the customers table by the input customer
number.
Second, use the simple CASE statement to determine the shipping time based on the country of
the customer. If the customer locates in USA , the shipping time is 2-day shipping . If the
customer locates in Canada , the shipping time is 3-day shipping . The customers from other
countries have 5-day shipping .
The following flowchart demonstrates the logic of the CASE statement for determining the
shipping time:
This statement calls the stored procedure and passes the customer number 112:
CALL GetCustomerShipping(112,@shipping);
The following statement returns the shipping time of the customer 112:
SELECT @shipping;
Here is the output:
+----------------+
| @shipping |
+----------------+
| 2-day Shipping |
+----------------+
1 row in set (0.00 sec)
MySQL LOOP
The LOOP statement allows you to execute one or more statements repeatedly.
[begin_label:] LOOP
statement_list
END LOOP [end_label]
The LOOP can have optional labels at the beginning and end of the block.
The LOOP executes the statement_list repeatedly. The statement_list may have one or more
statements, each terminated by a semicolon (;) statement delimiter.
Typically, you terminate the loop when a condition is satisfied by using the LEAVE statement.
This is the typical syntax of the LOOP statement used with LEAVE statement:
[label]: LOOP
...
-- terminate the loop
IF condition THEN
LEAVE [label];
END IF;
...
END LOOP;
The LEAVE statement immediately exits the loop. It works like the break statement in other
programming languages like PHP, C/C++, and Java.
In addition to the LEAVE statement, you can use the ITERATE statement to skip the current loop
iteration and start a new iteration. The ITERATE is similar to the continue statement in PHP,
C/C++, and Java.
MySQL LOOP statement example
The following statement creates a stored procedure that uses a LOOP loop statement:
DELIMITER $$
CREATE PROCEDURE LoopDemo()
BEGIN
DECLARE x INT;
DECLARE str VARCHAR(255);
SET x = 1;
SET str = '';
loop_label: LOOP
IF x > 10 THEN
LEAVE loop_label;
END IF;
SET x = x + 1;
IF (x mod 2) THEN
ITERATE loop_label;
ELSE
SET str = CONCAT(str,x,',');
END IF;
END LOOP;
SELECT str;
END$$
DELIMITER ;
In this example:
• The stored procedure constructs a string from the even numbers e.g., 2, 4, and 6.
• The loop_label before the LOOPstatement for using with
the ITERATE and LEAVE statements.
• If the value of x is greater than 10, the loop is terminated because of
the LEAVEstatement.
• If the value of the x is an odd number, the ITERATE ignores everything below it and
starts a new loop iteration.
• If the value of the x is an even number, the block in the ELSEstatement will build the
result string from even numbers.
CALL LoopDemo();
+-------------+
| str |
+-------------+
| 2,4,6,8,10, |
+-------------+
1 row in set (0.01 sec)
The WHILE loop is a loop statement that executes a block of code repeatedly as long as a
condition is true.
In this syntax:
If the search_condition evaluates to TRUE, the WHILE executes the statement_list as long as
the search_condition is TRUE.
The WHILE loop is called a pretest loop because it checks the search_condition before
the statement_list executes.
Second, specify one or more statements that will execute between the DO and END
WHILE keywords.
Third, specify optional labels for the WHILE statement at the beginning and end of the loop
construct.
First, create a table namedcalendars which stores dates and derived date information such as
day, month, quarter, and year:
Second, create a new stored procedure to insert a date into the calendars table:
DELIMITER $$
DELIMITER ;
Third, create a new stored procedure LoadCalendars() that loads a number of days starting
from a start date into the calendars table.
DELIMITER $$
END$$
DELIMITER ;
First, declare a counter and dt variables for keeping immediate values. The default values
of counter and dt are 1 and startDate respectively.
The WHILE loop repeatedly inserts dates into the calendars table until the counter is equal
to day.
The following statement calls the stored procedure LoadCalendars() to load 31 days into
the calendars table starting from January 1st 2019.
CALL LoadCalendars('2019-01-01',31);
The REPEAT statement executes one or more statements until a search condition is true.
[begin_label:] REPEAT
statement
UNTIL search_condition
END REPEAT [end_label]
The REPEAT executes the statement until the search_condition evaluates to true.
The REPEAT checks the search_condition after the execution of statement, therefore,
the statement always executes at least once. This is why the REPEAT is also known as a post-
test loop.
The REPEAT statement can have labels at the beginning and at the end. These labels are
optional.
This statement creates a stored procedure called RepeatDemo that uses the REPEAT statement
to concatenate numbers from 1 to 9:
DELIMITER $$
REPEAT
SET result = CONCAT(result,counter,',');
SET counter = counter + 1;
UNTIL counter >= 10
END REPEAT;
-- display result
SELECT result;
END$$
DELIMITER ;
First, declare two variables counter and result and set their initial values to 1 and blank.
The counter variable is used for counting from 1 to 9 in the loop. And the result variable is used
for storing the concatenated string after each loop iteration.
Second, append counter value to the result variable using the CONCAT() function until
the counter is greater than or equal to 10.
CALL RepeatDemo();
+--------------------+
| result |
+--------------------+
| 1,2,3,4,5,6,7,8,9, |
+--------------------+
1 row in set (0.02 sec)
MySQL LEAVE
The LEAVE statement exits the flow control that has a given label.
LEAVE label;
In this syntax, you specify the label of the block that you want to exit after the LEAVE keyword.
Using the LEAVE statement to exit a stored procedure
If the label is the outermost of the stored procedure or function block, LEAVE terminates the
stored procedure or function.
The following statement shows how to use the LEAVE statement to exit a stored procedure:
For example, this statement creates a new stored procedure that checks the credit of a given
customer in the customers table from the sample database:
DELIMITER $$
-- other logic
-- ...
END$$
DELIMITER ;
The LEAVE statement allows you to terminate a loop. The general syntax for
the LEAVE statement when using in the LOOP, REPEAT and WHILE statements.
[label]: LOOP
IF condition THEN
LEAVE [label];
END IF;
-- statements
END LOOP [label];
[label:] REPEAT
IF condition THEN
LEAVE [label];
END IF;
-- statements
UNTIL search_condition
END REPEAT [label];
The LEAVE causes the current loop specified by the label to be terminated. If a loop is enclosed
within another loop, you can break out of both loops with a single LEAVE statement.
Using LEAVE statement in a loop example
The following stored procedure generates a string of integer with the number from 1 to a
random number between 4 and 10:
DELIMITER $$
DELIMITER ;
CALL LeaveDemo(@result);
SELECT @result;
+------------------+
| @result |
+------------------+
| 1,2,3,4,5,6,7,8, |
+------------------+
1 row in set (0.00 sec)