CRUD Operations
Learn how to perform the four fundamental database operations — Create, Read, Update, Delete — against a MySQL table using PHP and MySQLi.
Introduction
You can now connect PHP to MySQL and run a single query. Real applications, though, need to do much more than that: they add new records, list existing ones, edit them, and eventually remove them. These four operations together are known as CRUD.
In this lesson, you will build a small, complete CRUD example against a `students` table, wrapping each operation in its own reusable PHP function.
- What CRUD stands for and why it is a useful mental model.
- How to write INSERT, SELECT, UPDATE, and DELETE queries with MySQLi.
- How to organize each operation into a small, reusable PHP function.
- Why building queries by directly inserting user input is dangerous.
What is CRUD?
CRUD stands for Create, Read, Update, and Delete — the four basic operations any application performs on stored data. Nearly every feature you can imagine in a real application, from posting a comment to editing a profile, boils down to one or more of these four operations.
Create
Add a brand-new row to a table — SQL: INSERT INTO.
Read
Retrieve existing rows from a table — SQL: SELECT.
Update
Modify an existing row's data — SQL: UPDATE.
Delete
Remove a row entirely — SQL: DELETE.
Setting Up the Table
This lesson uses a simple `students` table, the same shape introduced in the MySQL lesson. Assume it already exists, along with a shared MySQLi connection stored in `$conn`.
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age INT NOT NULL,
course VARCHAR(100)
);<?php
$conn = new mysqli("localhost", "root", "", "school");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>Create: Inserting Data
Create maps to the SQL INSERT statement. Here it is wrapped in a small function that takes the new student's details as arguments.
<?php
function createStudent($conn, $name, $age, $course) {
$sql = "INSERT INTO students (name, age, course) VALUES ('$name', $age, '$course')";
return $conn->query($sql);
}
if (createStudent($conn, "Amit Verma", 21, "PHP Development")) {
echo "Student added successfully!";
} else {
echo "Error: " . $conn->error;
}
?>Student added successfully!Read: Fetching Data
Read maps to SELECT. This function returns every student as an array of associative arrays, ready to loop over and display.
<?php
function getStudents($conn) {
$sql = "SELECT id, name, age, course FROM students";
$result = $conn->query($sql);
return $result->fetch_all(MYSQLI_ASSOC);
}
$students = getStudents($conn);
foreach ($students as $student) {
echo $student["name"] . " (" . $student["age"] . ") - " . $student["course"] . "\n";
}
?>Amit Verma (21) - PHP DevelopmentUpdate: Modifying Data
Update maps to the UPDATE statement, matching a specific row by its id so only that row changes.
<?php
function updateStudentCourse($conn, $id, $newCourse) {
$sql = "UPDATE students SET course = '$newCourse' WHERE id = $id";
return $conn->query($sql);
}
if (updateStudentCourse($conn, 1, "Advanced PHP")) {
echo "Student updated successfully!";
}
?>Student updated successfully!Delete: Removing Data
Delete maps to the DELETE statement, again matched by id so it removes only the intended row.
<?php
function deleteStudent($conn, $id) {
$sql = "DELETE FROM students WHERE id = $id";
return $conn->query($sql);
}
if (deleteStudent($conn, 1)) {
echo "Student deleted successfully!";
}
?>Student deleted successfully!Putting It All Together
With all four functions defined, a script can perform a full cycle of operations against the table using clear, descriptive function calls instead of scattering raw SQL strings everywhere.
<?php
require "db.php";
createStudent($conn, "Sara Khan", 23, "Web Design");
$students = getStudents($conn);
foreach ($students as $student) {
echo $student["name"] . "\n";
}
updateStudentCourse($conn, 2, "UI/UX Design");
deleteStudent($conn, 3);
$conn->close();
?>Wrapping each operation in a function keeps SQL logic in one place, makes the calling code read like plain English, and makes it much easier to fix or improve the query later without hunting through the whole codebase.
A Warning About User Input
Every example above builds its SQL by directly inserting values into a string with quotes and concatenation. That is fine for values you control, like the fixed examples here — but it becomes dangerous the moment any of those values come from user input, such as a form field.
<?php
// DO NOT do this with real user input
$name = $_POST["name"];
$sql = "INSERT INTO students (name, age, course) VALUES ('$name', 20, 'PHP')";
$conn->query($sql);
?>If $name came from a form and contained something like '); DROP TABLE students; --, the query above would run that attacker-controlled SQL. The next lesson, Prepared Statements, shows exactly how to prevent this.
Common Mistakes
- Forgetting the WHERE clause on an UPDATE or DELETE function, affecting every row.
- Not checking the return value of query() before assuming an operation succeeded.
- Repeating the same SQL string in multiple places instead of a single reusable function.
- Directly concatenating raw user input (like $_POST values) into a query string.
Best Practices
- Wrap each CRUD operation in a small, well-named function.
- Always pass an id (or another unique condition) to update and delete functions.
- Check the return value of every query() call and handle failures explicitly.
- Treat any value coming from a form or URL as untrusted — never insert it into SQL directly (covered next).
Frequently Asked Questions
Does CRUD always map exactly to these four SQL statements?
Almost always, yes: Create → INSERT, Read → SELECT, Update → UPDATE, Delete → DELETE. The mapping is simple and consistent across virtually every relational database.
Why organize CRUD logic into functions instead of writing SQL inline everywhere?
Functions keep related logic in one place, make calling code more readable, and mean you only need to fix a bug or add a safety improvement (like a prepared statement) in a single location.
Is it safe to use the examples in this lesson with real user input?
No. These examples build queries with string concatenation for clarity only. Any value coming from a user must go through a prepared statement, covered in the next lesson.
What happens if I forget the WHERE clause on updateStudentCourse?
Every row in the table would be updated with the new course, since MySQL applies the SET clause to every matching row — and without WHERE, every row matches.
Can one function handle more than one CRUD operation?
It is possible, but it is considered better practice to keep each function focused on a single operation, which keeps code easier to read, test, and reuse.
Key Takeaways
- CRUD stands for Create, Read, Update, Delete — the four fundamental data operations.
- Each operation maps directly to an SQL statement: INSERT, SELECT, UPDATE, DELETE.
- Wrapping each operation in a small function keeps code organized and reusable.
- Update and Delete functions must always filter by a unique condition like id.
- Building queries by concatenating raw user input is dangerous and must be fixed with prepared statements.
Summary
CRUD operations are the backbone of nearly every data-driven feature you will build. With createStudent(), getStudents(), updateStudentCourse(), and deleteStudent(), you now have a working, reusable pattern for managing records in MySQL from PHP.
In this lesson, you implemented all four CRUD operations against a students table and saw why directly inserting user input into these queries is unsafe. Next, you will fix that exact problem using prepared statements.
- You know what CRUD stands for and how it maps to SQL.
- You implemented Create, Read, Update, and Delete with MySQLi.
- You organized each operation into a small, reusable function.
- You understand why raw user input in SQL queries is dangerous.