Skip to main content
MySQL Basics
CHAPTER 21 Beginner

Stored Procedures and Functions

Updated: May 16, 2026
6 min read

# CHAPTER 21

Stored Procedures and Functions

1. Introduction

If you are building an enterprise application, you might have a web app written in PHP, a mobile app written in Swift, and an internal dashboard written in Python. If all three apps need to run the complex "Checkout Transaction" we built in Chapter 20, you would have to write and maintain that exact same SQL code in three different programming languages! To solve this, we use Stored Procedures. We save the logic permanently *inside* MySQL. The apps simply call the procedure. In this chapter, we turn MySQL into a programming language.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the architectural benefits of Stored Procedures.
  • Create a Stored Procedure using the DELIMITER command.
  • Pass input parameters (IN) to a procedure.
  • Create User-Defined Functions (UDF) for inline calculations.
  • Execute a procedure using the CALL statement.

3. What is a Stored Procedure?

A Stored Procedure is exactly like a function in PHP or JavaScript. It is a block of pre-compiled SQL code saved inside the database dictionary.
  • Security: You can grant an app permission to run the procedure without giving it permission to access the underlying tables!
  • Performance: Because the procedure is pre-compiled by the MySQL engine, it executes faster than sending raw SQL strings over the network.
  • Maintainability: "Don't Repeat Yourself." If the checkout logic changes, you update the database once, and all three apps (Web, iOS, Android) instantly use the new logic!

4. Creating a Stored Procedure

Because a procedure contains multiple SQL statements separated by semicolons (;), we must temporarily change MySQL's default delimiter. Otherwise, MySQL will stop reading the procedure at the first semicolon it sees!
sql
12345678910111213
-- Step 1: Change the delimiter from ; to //
DELIMITER //

-- Step 2: Create the Procedure
CREATE PROCEDURE GetHighValueCustomers()
BEGIN
    SELECT first_name, email 
    FROM users 
    WHERE total_spent > 1000;
END //

-- Step 3: Change the delimiter back to standard ;
DELIMITER ;

5. Executing the Procedure

Once saved, your PHP or Python application simply needs to send one word to the database: CALL.
sql
1
CALL GetHighValueCustomers();

6. Using Parameters (IN variables)

Procedures become infinitely more powerful when you pass variables into them, just like function arguments in programming. We use the IN keyword.
sql
123456789101112131415
DELIMITER //

-- We define an input parameter named p_department of type VARCHAR
CREATE PROCEDURE GetEmployeesByDept(IN p_department VARCHAR(50))
BEGIN
    SELECT first_name, salary 
    FROM employees 
    WHERE department = p_department;  -- We use the parameter here!
END //

DELIMITER ;

-- To use it:
CALL GetEmployeesByDept('IT');
CALL GetEmployeesByDept('Sales');

7. User-Defined Functions (UDF)

While Procedures are called using CALL to execute large workflows, Functions are designed to calculate a specific value and return it inline inside a standard SELECT query.

*Let's build a function that calculates a 10% discount on any price passed to it.*

sql
12345678910111213141516
DELIMITER //

CREATE FUNCTION CalculateDiscount(price DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
    DECLARE discount_price DECIMAL(10,2);
    SET discount_price = price * 0.90;
    RETURN discount_price;
END //

DELIMITER ;

-- How to use the Function:
SELECT product_name, price, CalculateDiscount(price) AS sale_price 
FROM products;

8. Mini Project: The Transfer Funds Procedure

Let's convert our vulnerable transaction from Chapter 20 into an indestructible, reusable Stored Procedure that takes parameters!
sql
1234567891011121314
DELIMITER //
CREATE PROCEDURE TransferFunds(IN sender_id INT, IN receiver_id INT, IN amount DECIMAL(10,2))
BEGIN
    START TRANSACTION;
    
    UPDATE accounts SET balance = balance - amount WHERE id = sender_id;
    UPDATE accounts SET balance = balance + amount WHERE id = receiver_id;
    
    COMMIT;
END //
DELIMITER ;

-- The web app just sends this:
CALL TransferFunds(1, 2, 500.00);

9. Common Mistakes

  • Forgetting the DELIMITER: If you attempt to write a multi-line procedure with standard semicolons without changing the delimiter first, MySQL will throw a syntax error on line 2.
  • Putting too much logic in MySQL: While Procedures are powerful, MySQL is difficult to debug. Do not put massive amounts of String Manipulation or complex array processing inside the database. Use Python/PHP for heavy business logic, and use MySQL purely for data routing and transactions.

10. Best Practices

  • Parameter Naming: Always prefix your parameters (e.g., pdepartment or indepartment). If you name your parameter exactly the same as the column name (e.g., department), MySQL gets confused during the WHERE department = department clause and will return all rows!

11. Exercises

  1. 1. Write the CALL statement required to execute a procedure named DeleteInactiveUsers.
  1. 2. Why is it necessary to change the DELIMITER when writing a Stored Procedure?

12. MCQ Quiz with Answers

Question 1

What is the primary architectural benefit of utilizing Stored Procedures in an enterprise application?

Question 2

How does a User-Defined Function differ from a Stored Procedure in MySQL?

13. Interview Questions

  • Q: Describe a security scenario where granting a web application permission to CALL a Stored Procedure is vastly safer than granting it UPDATE and DELETE permissions on the underlying tables.
  • Q: Explain the purpose of the DELIMITER // command when writing MySQL routines.

14. FAQs

Q: Can a Stored Procedure return data, or only execute Updates/Deletes? A: Yes! If a procedure contains a SELECT * FROM... statement, executing CALL ProcedureName() will return the resulting grid of data back to your PHP/Python application just like a normal query.

15. Summary

Stored Procedures and Functions transform MySQL from a passive storage container into an active, programmable engine. By encapsulating logic, utilizing input parameters, and wrapping code in transactions, you elevate your database architecture to enterprise standards.

16. Next Chapter Recommendation

Procedures are great, but they require a human or an app to explicitly CALL them. What if we want the database to react *automatically*? What if we want to log an audit trail the exact millisecond a salary is changed, without the PHP backend doing anything? In Chapter 22: Triggers in MySQL, we master database automation.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·