CHAPTER 12
Beginner
Connecting Express.js with MySQL
Updated: May 14, 2026
30 min read
# CHAPTER 12
Connecting Express.js with MySQL
1. Introduction
While MongoDB is extremely popular in the Node.js ecosystem, much of the world's enterprise data still lives in Relational Databases (SQL). If you are building financial software, inventory management systems, or applications where data is heavily interconnected (e.g., Users have many Orders, Orders have many Products), a relational database is superior. In this chapter, we will learn how to connect Express to MySQL, execute SQL queries using Promises, and return structured relational data.2. Learning Objectives
By the end of this chapter, you will be able to:- Differentiate between NoSQL (MongoDB) and SQL (MySQL) paradigms.
-
Install and configure the
mysql2package.
- Create a reusable MySQL connection pool.
-
Execute raw SQL queries asynchronously using
async/await.
3. Beginner-Friendly Explanation
Imagine organizing a massive corporate office.- MongoDB is a series of file folders. You can put a resume, a photo, and a contract all inside "Alice's Folder." It is flexible, but hard to generate complex reports.
- MySQL is a series of massive Excel Spreadsheets. Data must fit perfectly into rows and columns. "Alice" goes in the User sheet. Her "Purchases" go in the Order sheet. The sheets are linked together by ID numbers. It is strict, rigid, but incredibly powerful for math, accounting, and complex relationships.
4. Step 1: Installing the Driver
Historically, themysql package in Node.js relied heavily on "callbacks," which resulted in messy code. Today, the industry standard is mysql2, which natively supports modern async/await Promises.
bash
5. Step 2: Creating a Connection Pool
Connecting to a database takes time. If 1,000 users hit your API, opening and closing 1,000 separate database connections will crash your server. Instead, we create a Connection Pool. The pool opens 10 connections and keeps them alive in the background. When a user requests data, the API borrows a connection for a millisecond, does the query, and returns the connection to the pool.Create a file: config/db.js
javascript
6. Step 3: Executing SQL Queries
Now we import the pool into our Controller and execute raw SQL queries.In controllers/productController.js:
javascript
7. Preventing SQL Injection
Never, ever concatenate strings to build a SQL query. If you write:const sql = "SELECT * FROM users WHERE email = '" + req.body.email + "'";
A hacker can type ' OR 1=1; DROP TABLE users; into the email input box on your website. Your server will execute the command and delete your entire database.
ALWAYS use the question mark ? placeholders (Parameterized Queries) as shown in Step 6. The mysql2 package will automatically sanitize the input and neutralize malicious commands.
8. Backend Workflow: Object Relational Mappers (ORMs)
Writing raw SQL strings (like'SELECT * FROM products') can become very difficult to manage in massive applications with 50 tables.
While MongoDB uses Mongoose (an ODM), SQL databases use ORMs (Object Relational Mappers). Popular Node.js ORMs include Sequelize and Prisma. They allow you to write SQL queries using JavaScript methods (e.g., Product.findAll()) instead of raw strings. However, knowing raw SQL via mysql2 is a prerequisite to understanding how ORMs work under the hood.
9. Best Practices
-
Environment Variables: Just like MongoDB, never hardcode your MySQL password into
config/db.js. Always useprocess.env.DB_PASSWORD.
10. Common Mistakes
-
Forgetting Destructuring: The
db.query()method returns an array with two things: the data rows, and the field metadata. Beginners often writeconst data = await db.query(...)and then try to returnres.json(data). The frontend receives a massive, confusing object containing thousands of lines of metadata. Always destructure the first item from the array:const [rows] = await db.query(...).
11. Exercises
-
1.
Explain the architectural and performance benefits of using a Connection Pool (
mysql.createPool) versus creating a single connection (mysql.createConnection) for every incoming HTTP request.
12. Coding Challenges
-
Challenge: Write the controller logic for a
getProductByIdfunction. Usedb.query()with aSELECTstatement and aWHERE id = ?clause. Extract the specific product from the returned array and send it back as JSON. Handle the case where the array is empty (product not found).
13. MCQs with Answers
Question 1
What is the primary purpose of the question mark (?) placeholder in a mysql2 query like SELECT * FROM users WHERE age = ??
Question 2
When migrating from legacy Node.js code to modern standards, why is the mysql2 package preferred over the older mysql package?
14. Interview Questions
- Q: Explain the concept of SQL Injection. How does a hacker execute it, and how exactly do parameterized queries prevent it from occurring?
- Q: Compare and contrast the use case for a relational database (MySQL) versus a document database (MongoDB) when designing the backend for a new web application.
15. FAQs
Q: Can I use PostgreSQL instead of MySQL? A: Absolutely. PostgreSQL is actually preferred by many senior developers. The concepts are identical, but you would install thepg package instead of mysql2.
16. Summary
In Chapter 12, we bridged the gap between Node.js and Relational Databases. We learned how to utilize the modernmysql2 package to create high-performance Connection Pools, execute raw SQL commands asynchronously, and safely extract structured data. Most importantly, we addressed the critical security vulnerability of SQL Injection by enforcing the use of Parameterized Queries.