C is a programming language widely used in various applications. It is a powerful tool typically used to interface with MySQL database, a very popular database management system.
Querying MySQL database queries directly in C is very efficient and is one of the core skills that any web developer must have in their toolkit.
This article will provide a step-by-step guide on using C to query MySQL, allowing you to save, retrieve, and update data, at least at a basic level.
- Understanding the Prerequisites
- Setting Up Your Development Environment
- Establishing a Connection to the MySQL Server
- Crafting and Executing SQL Queries
- Fetching and Processing Results
- Error Handling and Debugging
- Closing the Connection and Cleaning Up
- Putting It All Together: A Complete Example

1. Understanding the Prerequisites
The first step in using MySQL database queries is to prepare them. This includes the tools necessary for development and connectivity.
These requirements would include the MySQL C API via the libmysqlclient library. Different operating systems may have other steps to install this API, but it is typically included once you install a MySQL Server distribution.
Of course, you would also need to have an IDE for C as well as the standard C library headers like stdio.h and mysql.h. There are several applications for C developers that can provide easy development and connectivity to MySQL.
Aside from a basic understanding of C and MySQL, you are ready to start with the next step: querying MySQL database servers in C.

2. Setting Up Your Development Environment
Once you have a C compiler such as GCC, it needs to be configured so that it can run with your IDE. This is an example of how to do this using Visual Studio Code.
You also need to ensure that MySQL client libraries and headers are available so that you can compile and link your program to the database.
This process can be done by using the -lmysqlclient flag during compilation. A sample code to do this is indicated here:
gcc -o myapp myapp.c -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient
This setup helps you configure your C development environment to connect to your MySQL database.

3. Establishing a Connection to the MySQL Server
Before you start coding, include the header file so that MySQL C API functions and data types become available. You can add the MySQL header file by adding this at the beginning of your code:
#include <mysql/mysql.h>
You can then establish a MySQL database connection using the code below, specifying important parameters such as host, username, password, database name, and port to be used.
A sample code is listed below.
MYSQL *conn = mysql_init(NULL);
if (conn == NULL) {
fprintf(stderr, “mysql_init() failed\n”);
exit(EXIT_FAILURE);
}
if (mysql_real_connect(conn, “host”, “username”, “password”, “database name”, 0, NULL, 0) == NULL) {
fprintf(stderr, “mysql_real_connect() failed\n”);
mysql_close(conn);
exit(EXIT_FAILURE);
}
If the connection succeeds, then we are ready for the next step.

4. Crafting and Executing SQL Queries
MySQL queries are required to perform operations such as SELECT, INSERT, UPDATE, and DELETE statements. The mysql_query() function sends commands for the MySQL server to execute.
A sample SELECT statement to the MySQL server using C is indicated below.
if (mysql_query(conn, “SELECT id, name FROM users”)) {
fprintf(stderr, “Query failed: %s\n”, mysql_error(conn));
mysql_close(conn);
exit(EXIT_FAILURE);
}
The retrieved data can now be fetched and processed. This will be discussed in the next section.

5. Fetching and Processing Results
Results from an SQL query, particularly from SELECT statements, can be obtained using either the mysql_store_result() or mysql_use_result() functions.
The mysql_store_result() function retrieves all results from the query at once but consumes more memory. On the other hand, the mysql_use_result() fetches one row at a time, which is best for processing larger datasets.
You may also use the mysql_fetch_row() function. This returns an array of strings, which you can retrieve through iterative statements.
An example of the mysq_store_result() function is displayed below.
MYSQL_RES *result = mysql_store_result(conn);
if (result == NULL) {
fprintf(stderr, “Retrieving result failed: %s\n”, mysql_error(conn));
mysql_close(conn);
exit(EXIT_FAILURE);
}
This next sample utilizes the mysql_fetch_row() function to display all retrieved data.
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
printf(“ID: %s, Name: %s\n”, row[0], row[1]);
}
Make it a point to free resources to prevent memory leaks. This can be done by using the mysql_free_result() function at the end of your function.

6. Error Handling and Debugging
Error handling is essential when working with MySQL databases in C. Robustness is required to check and catch failure codes from MySQL. You should also be able to check return values, such as non-ero returns for the myself_query() function.
Functions like mysql_error() and mysql_errno() may also be used to get information about the error your application is throwing.
Catching these errors is necessary to detect problems with your code or other issues. You may also use debugging flags and other tools to help you trace other problems with the application.

7. Closing the Connection and Cleaning Up
Any application requires proper resource management, and C is no exception. This is especially true when working with large datasets and databases such as MySQL.
When querying MySQL database servers with C, you may utilize the sample code below to release allocated resources, terminate connections, and avoid memory leaks.
Proper resource management is crucial in C, especially when working with external systems like MySQL. After your program finishes interacting with the MySQL database, ensure all allocated resources are released to avoid memory leaks or hanging connections.
mysql_free_result(result);
mysql_close(conn);
Make it a point to call the mysql_library_end() function before the program ends if you initialize the MySQL library with mysql_library_init() as good programming practice, especially for larger and more complicated systems.

8. Putting It All Together: A Complete Example
A complete sample code for all the above concepts is displayed below.
In this example, the application retrieves data from a table and prints it individually. It also calls all prerequisite packages, catches any errors, and cleans up resources once the MySQL database connection is no longer required.
#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>
int main() {
MYSQL *conn;
MYSQL_RES *result;
MYSQL_ROW row;
conn = mysql_init(NULL);
if (conn == NULL) {
fprintf(stderr, “mysql_init() failed\n”);
return EXIT_FAILURE;
}
if (mysql_real_connect(conn, “localhost”, “user”, “password”, “testdb”, 0, NULL, 0) == NULL) {
fprintf(stderr, “mysql_real_connect() failed: %s\n”, mysql_error(conn));
mysql_close(conn);
return EXIT_FAILURE;
}
if (mysql_query(conn, “SELECT id, name FROM users”)) {
fprintf(stderr, “Query failed: %s\n”, mysql_error(conn));
mysql_close(conn);
return EXIT_FAILURE;
}
result = mysql_store_result(conn);
if (result == NULL) {
fprintf(stderr, “Retrieving result failed: %s\n”, mysql_error(conn));
mysql_close(conn);
return EXIT_FAILURE;
}
while ((row = mysql_fetch_row(result))) {
printf(“ID: %s, Name: %s\n”, row[0], row[1]);
}
mysql_free_result(result);
mysql_close(conn);
return EXIT_SUCCESS;
}
This application can be run on Linux by running the following command:
gcc -o mysql_example mysql_example.c `mysql_config –cflags –libs`
If successful, you will see all names displayed from the users table of your testdb database.
Conclusion
Querying MYSQL database servers in C may initially seem complicated. Still, once you understand the concepts and follow the steps mentioned above, you will see that it is very easy to set up and execute.
Using MySQL and C is perfect for simple applications, and it can also prepare you, experience-wise, for more complicated application development and more advanced database systems.
However, never forget fundamentals and standards such as error handling and resource cleanup. These basics apply to programs of any size and complexity, ensuring efficient and robust systems that can deliver the results and performance you want.
