Stored Procedures in MySQL and PHP

Share this article

Put simply, a Stored Procedure (“SP”) is a procedure (written in SQL and other control statements) stored in a database which can be called by the database engine and connected programming languages.

In this tutorial, we will see how to create an SP in MySQL and execute it in MySQL server and in PHP.

Note: We are not going to cover the full aspect of the SP here. The official MySQL document should always be the place for reference.

SP are also available in other common database servers (Postgre for example) so what we will discuss here can be applied to those as well.

Why Stored Procedures are recommended

Most of us are quite familiar with the normal setup to build a database application: creating database, creating tables, set up indexes, CRUD the data, issue queries from the client side and do further processing if necessary.

That workflow works fine in most cases but there is one important aspect of database programming missing: the Stored Procedure.

There are at least four advantages I can think of to use an SP in a database application.

Firstly, it reduces the network traffic and overhead. In a typical PHP database web application, there are four layers:

  • The client layer, which is normally a web browser. It receives user interactions and presents the data in a UI.
  • The web server layer, which handles and dispatches user requests and sends back responses to the client layer.
  • The PHP layer, which handles all PHP interpretation, does the application logic and generates the PHP part of response.
  • The database layer, which handles all database queries, including but not limited to a SELECT query, an INSERT statement, etc.

In a typical environment, these layers will most likely not reside on one single machine, maybe not even in one network, for larger applications.

Although network speed has tremendously increased in the past few years, it is still the slowest and most unreliable compared to other ways of transferring the data (CPU cache, memory, hard disk, etc). So, to save bandwidth and increase robustness, it is sometimes a good idea to have more processing and logic done on the server side (in particular, the MySQL server) and have less data transferred through the network.

Secondly, it improves the performance. SP is stored and run directly in the MySQL server. It can be pre-compiled and analyzed by the database server. This is quite different from issuing the same query from the client side, where the query will be parsed by database drivers, analyzed and optimized (if possible) every time the query statement is called. This is somehow quite like the interpreted language execution (at the client end) and the compiled language execution (at the database server end). And we know a compiled program will run faster.

Third, Write Once and Execute Anywhere. SQL is standard and purely 100% platform independent. It only relies on the database server. Consider how many different languages/libs there are that we can use to deal with the database. It increases efficiency to put the data retrieving and processing at the server end instead of writing the same processing logic in a different syntax provided by all these languages/libs, if the data processing logic is so commonly used.

Last but not least, SP is a fundamental aspect of database security.

Let’s consider a simple database setup. In a human resource information system (HRIS), it is reasonable to assume that there exists a table holding the salary information of each employee. An HR employee should have the right to grab some figures out of this table: total salary, average salary, etc but this employee should not see the detailed salary of each employee as this information will be too sensitive and should only be available to a few.

We know MySQL has a comprehensive privilege control. In this case, it is obvious that we can’t even grant SELECT privilege to this HR employee (which, if we do, means he/she can see the detailed salary of everyone). But if he/she can’t access the salary table, how can this employee get the aggregation information related to salary? How can we allow the employee to grab that information without compromising the HR policy?

The answer is using a Stored Procedure that returns the required information and grants that employee the EXECUTE privilege. (For a detailed list and explanation of MySQL privileges, please consult the official documentation. The link here is for MySQL 5.6. Please replace 5.6 with the version you are using.)

SP is now a bridge, bridging the user (our HR employee) and the table (salary), to which the user has no direct access.

That’s it! With SP, we can get the user to accomplish the task without compromising the database security (and HR policy)!

Drawbacks of using Stored Procedures

After naming all the advantages of using an SP, we need to be clear about some of the drawbacks and see if there are ways to improve.

  • No version control on SP itself. When an SP is modified, it is modified, no historical trails can be kept in the server side. It may create some frustrations when the user would like to rollback a change. My suggestion is to write the SP in your client side and put it under version control. When the SP is ready, it is easy to copy the code into, say MySQL Workbench and create it at the server side. By doing so, we can have some degree of version control.
  • No easy way to “synchronize” the changes applied and force everyone to use the latest version, in particular, when each of the team member has his/her own local database for development and testing purposes. Version control may be the solution but still requires manual intervention by updating the local copy of the SP in the local db server. Another way is to use “mocking”. The team members can be divided so that at least one person will focus on the maintenance of the SP and the implementation of the calling to SP in the code. All others that need the results from the SP can develop and test their portion using mocking objects, i.e, always assuming the “faked” call to the SP will return a desired result. In a later stage, merging can be done to discard the mocking code.
  • Hard to backup/export. The SP is on the server side. Regular developers will only have basic privileges (SELECT, EXECUTE, etc) and no admin rights to backup and export. In a way, I won’t call it a drawback but rather a fundamental aspect of db security. There is no way, and it is not recommended to get around this. It is suggested that, in a team, a dedicated DB admin will be appointed to do such jobs. A regular db backup can also serve the backup/export (and import) purpose.

Creating a Stored Procedure in MySQL

As SPs are stored in the server, it is recommended to create the SP directly in the server, i.e., not by using PHP or other programming languages to issue SQL commands to do so.

Let’s see how to create the SP in MySQL server, create a user and apply privileges and run (as that user) the SP to see if the result is correct. In my working environment, I am using MySQL Workbench. Other tools are available (PHPMyAdmin for example) so feel free to use the tools that best fit you.

Assume we have a table like this:

CREATE TABLE `salary` (
  `empid` int(11) NOT NULL,
  `sal` int(11) DEFAULT NULL,
  PRIMARY KEY (`empid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

And for the HR employee that needs to get the aggregated information on salary (average, max, min, etc) from that table, we first create a user 'tr' like this:

CREATE USER 'tr'@'localhost' IDENTIFIED BY 'mypass';

and for this user, we only grant EXECUTE privilege to the schema where the salary table resides:

grant execute on hris.*  to tr@`%`

We can verify the necessary privilege is granted by visiting the “Users and Privileges” in MySQL Bench:

Now let’s create the SP like this:

DELIMITER $$

CREATE PROCEDURE `avg_sal`(out avg_sal decimal)
BEGIN
    select avg(sal) into avg_sal from salary;

END

NOTE: All the above operations will require an admin role in the MySQL server.

After issuing the command in MySQL Workbench, the avg_sal SP will be created and ready to be called. It will return the average salary of table salary.

To test if the user tr can actually run the SP but should not be able to access the salary table, we can switch the role by logging into the MySQL server using user tr. It can be done by creating another connection in MySQL Workbench using a different user/password pair.

After logging in as tr, the first thing we will notice is that the user will not be able to see any tables and can only see the SP:

It is clear that the user tr won’t be able to select anything from any table (thus unable to see the detailed salary number of the salary table) but he/she is able to execute the SP we just created and get the average salary of the company:

call avg_sal(@out);
select @out;

The average salary will be displayed.

We have so far done all the preparation to create a user, grant privileges, create a SP and test the running of the SP. Next we will show how to call that SP from within PHP.

Calling a Stored Procedure from PHP

With PDO, calling an SP is straightforward. The PHP code is as follows:

$dbms = 'mysql';

//Replace the below connection parameters to fit your environment
$host = '192.168.1.8'; 
$db = 'hris';
$user = 'tr';
$pass = 'mypass';
$dsn = "$dbms:host=$host;dbname=$db";

$cn=new PDO($dsn, $user, $pass);

$q=$cn->exec('call avg_sal(@out)');
$res=$cn->query('select @out')->fetchAll();
print_r($res);

The $res will contain the average salary of the table salary. The user can further process the output with PHP now.

Conclusion

In this article, we reviewed the long-forgotten component in MySQL database: the Stored Procedure. The advantages to use an SP are obvious and let me re-emphasize: Stored Procedures allow us to apply stronger database access control to certain data to fit in with the business requirement.

We also illustrated the basic steps to create Stored Procedures, create a user and assign a privilege, and how to call it in PHP.

This article does not cover the full scope of Stored Procedures. Some important aspects like input/output parameters, control statement, cursors, the complete syntax, etc are not discussed in this short article.

If you feel interested, please leave your comments here and we will be glad to bring more in-depth articles about this useful and powerful aspect of MySQL.

Frequently Asked Questions (FAQs) about Stored Procedures in MySQL and PHP

What are the benefits of using stored procedures in MySQL with PHP?

Stored procedures in MySQL offer several advantages when used with PHP. They help in enhancing the performance of your applications. Since the procedures are stored on the server side, they are processed more quickly and efficiently, reducing the amount of information sent between the server and the client. They also improve productivity as you can reuse the same stored procedure in multiple applications. Moreover, they provide better security as you can grant permission to users to execute the procedure without giving them access to underlying database tables.

How can I handle errors in MySQL stored procedures using PHP?

Error handling in MySQL stored procedures can be done using SQL exception handlers. You can declare a handler for a specific condition or SQLSTATE value. When an error occurs, the handler will be invoked and you can perform necessary actions like rolling back the transaction or logging the error. In PHP, you can use the mysqli_sql_exception class to catch exceptions thrown by MySQLi functions.

Can I use stored procedures with PHP Data Objects (PDO)?

Yes, you can use stored procedures with PHP Data Objects (PDO). PDO provides a consistent interface for accessing databases in PHP. You can call a stored procedure in your SQL query using the CALL SQL statement. Then, you can use the PDOStatement::execute() method to run the query.

How can I return a result set from a stored procedure in MySQL using PHP?

To return a result set from a stored procedure, you can use a SELECT statement in your stored procedure. Then, in PHP, you can use the mysqli_query or PDO::query method to execute the stored procedure and the mysqli_fetch_assoc or PDOStatement::fetch method to fetch the result set.

Can I pass parameters to a stored procedure in MySQL using PHP?

Yes, you can pass parameters to a stored procedure in MySQL using PHP. In your stored procedure, you can define IN, OUT, and INOUT parameters. Then, in PHP, you can bind the parameters to your SQL query using the mysqli_stmt_bind_param or PDOStatement::bindParam method.

How can I modify a stored procedure in MySQL?

You can modify a stored procedure in MySQL using the ALTER PROCEDURE statement. This statement allows you to change the characteristics of a stored procedure like its parameter list or body. However, you cannot change the name of a stored procedure. If you want to change the name, you need to drop and recreate the procedure.

How can I debug a stored procedure in MySQL?

Debugging a stored procedure in MySQL can be a bit tricky as MySQL does not provide a built-in debugger for stored procedures. However, you can use techniques like using SELECT statements to display intermediate results or using a table to log debug information.

Can I call a stored procedure within another stored procedure in MySQL?

Yes, you can call a stored procedure within another stored procedure in MySQL. This is known as a nested call or a stored procedure recursion. However, you should be careful with recursive calls as they can lead to infinite loops if not handled properly.

How can I improve the performance of my stored procedures in MySQL?

There are several ways to improve the performance of your stored procedures in MySQL. You can use indexes to speed up your queries, avoid using cursors as they can be slow, use local variables instead of repeated expression evaluations, and avoid using unnecessary loops and conditional statements.

How can I handle transactions in stored procedures in MySQL using PHP?

You can handle transactions in stored procedures by using the START TRANSACTION, COMMIT, and ROLLBACK statements. In PHP, you can use the mysqli_begin_transaction or PDO::beginTransaction method to start a transaction, the mysqli_commit or PDO::commit method to commit the transaction, and the mysqli_rollback or PDO::rollBack method to rollback the transaction.

Taylor RenTaylor Ren
View Author

Taylor is a freelance web and desktop application developer living in Suzhou in Eastern China. Started from Borland development tools series (C++Builder, Delphi), published a book on InterBase, certified as Borland Expert in 2003, he shifted to web development with typical LAMP configuration. Later he started working with jQuery, Symfony, Bootstrap, Dart, etc.

databasemariaDBmysqlpermissionsPHPsecuritystored procedure
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week