All posts
PHPSeptember 21, 20267 min read

How to Select and Display Data From MySQL With PHP

Learn how to select data from a MySQL database with PHP using mysqli. Step-by-step code to fetch rows and display them safely in an HTML table.

F
Fepiq Team
Fepiq

Want to know how to select data from a MySQL database with PHP? Here is the short answer: you connect to the database with mysqli_connect(), run a SELECT query with mysqli_query(), then loop over the results with mysqli_fetch_assoc() to print each row. This guide walks through every step with small, copy-pasteable examples, so you can go from an empty page to a working table of data in a few minutes.

This post assumes you already have a MySQL table with some data in it. If you have not connected PHP to MySQL yet, start with our guide on how to connect PHP to a MySQL database, then come back here.

What you need before you start

  • PHP installed and running (locally with XAMPP/MAMP, or on a server).
  • A MySQL database with at least one table that has some rows in it. This guide uses a table named students with columns id, name, and email.
  • The mysqli extension, which comes built in with most PHP installations.
  • A text editor and basic comfort saving .php files.

Step 1: Connect to your MySQL database

Every SELECT query starts with a connection. Save this as connect.php:

php
<?php
$host = "localhost";
$user = "root";
$password = "";
$database = "school";

$conn = mysqli_connect($host, $user, $password, $database);

if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}
?>

$host, $user, $password, and $database are the details MySQL needs to let you in. mysqli_connect() uses them to open a connection and returns a connection object, or false if it fails. The if (!$conn) check catches a failed connection, and die() stops the script immediately while printing the reason with mysqli_connect_error(). This stops the rest of the page from running with no working database link.

Step 2: Write a SELECT query in PHP

With a connection open, you can send a SQL query as a plain string:

php
<?php
$sql = "SELECT id, name, email FROM students";
$result = mysqli_query($conn, $sql);
?>

$sql is just a text string holding a normal SQL SELECT statement. mysqli_query($conn, $sql) sends that string to MySQL over the connection you opened in Step 1. If the query succeeds, $result holds a result set: an object you can loop through to read each row. If the query has a mistake, mysqli_query() returns false instead.

Step 3: Fetch rows with mysqli_fetch_assoc()

A result set on its own is not readable text yet. You pull rows out of it one at a time in a loop:

php
<?php
while ($row = mysqli_fetch_assoc($result)) {
    echo $row["name"] . " - " . $row["email"] . "\n";
}
?>

mysqli_fetch_assoc($result) returns the next row as an associative array, meaning you can read each value by column name, like $row["name"]. It returns null once there are no rows left, which is exactly the condition a while loop needs to stop on its own. Each time through the loop, $row holds one record from your table.

Step 4: Display the data in an HTML table

Mixing that loop with HTML is how you turn raw rows into a table a visitor can actually read:

php
<?php
$sql = "SELECT id, name, email FROM students";
$result = mysqli_query($conn, $sql);
?>
<table border="1">
  <tr>
    <th>ID</th>
    <th>Name</th>
    <th>Email</th>
  </tr>
  <?php while ($row = mysqli_fetch_assoc($result)): ?>
  <tr>
    <td><?php echo htmlspecialchars($row["id"]); ?></td>
    <td><?php echo htmlspecialchars($row["name"]); ?></td>
    <td><?php echo htmlspecialchars($row["email"]); ?></td>
  </tr>
  <?php endwhile; ?>
</table>

The while (...): ... endwhile; syntax is an alternative loop style that reads more cleanly inside HTML than curly braces do. Each pass prints one table row. htmlspecialchars() converts any special characters (like < or &) in the data into safe text, which stops stored data from accidentally breaking your page or running as code in the browser.

Selecting specific rows with WHERE

Often you do not want every row, just one that matches something, like a specific ID. Never paste a variable straight into the SQL string for this. Use a prepared statement instead, which keeps user input separate from the query:

php
<?php
$studentId = 5;

$sql = "SELECT id, name, email FROM students WHERE id = ?";
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, "i", $studentId);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
?>

The ? in the query is a placeholder for a value that gets filled in safely. mysqli_prepare() builds the query without the value yet. mysqli_stmt_bind_param($stmt, "i", $studentId) attaches $studentId to that placeholder, where "i" tells MySQL to treat it as an integer. mysqli_stmt_execute() runs the query, and mysqli_stmt_get_result() converts the result into the same kind of result set you already know how to loop through with mysqli_fetch_assoc().

Handling no results

A query can succeed but still return zero rows, for example searching for an ID that does not exist. Check for that before looping:

php
<?php
if (mysqli_num_rows($result) === 0) {
    echo "No students found.";
} else {
    while ($row = mysqli_fetch_assoc($result)) {
        echo $row["name"] . "\n";
    }
}

mysqli_close($conn);
?>

mysqli_num_rows($result) counts how many rows came back, so you can show a friendly message instead of an empty table. mysqli_close($conn) closes the database connection once you are done with it, which is good practice at the end of a script.

FunctionWhat it does
mysqli_connect()Opens a connection to the MySQL database
mysqli_query()Sends a SQL string and returns a result set
mysqli_fetch_assoc()Returns the next row as a name-value array
mysqli_num_rows()Counts how many rows a result set contains
mysqli_prepare() / bind_param()Safely inserts a variable into a query
mysqli_close()Closes the database connection

Now that you can display data, the natural next step is learning how to change it.

Read the update & delete guide

Common mistakes to avoid

  • Putting a variable directly inside the SQL string, like "WHERE id = $id" — this opens the door to SQL injection. Use a prepared statement instead.
  • Forgetting to check if mysqli_query() returned false before looping over $result.
  • Skipping htmlspecialchars() when printing data that came from users, which can let malicious code run in the browser.
  • Not closing the connection with mysqli_close() at the end of long-running scripts.
  • Selecting every column with SELECT * when you only need a few — naming columns explicitly is clearer and often faster.

Frequently asked questions

What is the difference between mysqli_fetch_assoc and mysqli_fetch_array?+

mysqli_fetch_assoc() returns each row as an associative array, so you access values by column name like $row["name"]. mysqli_fetch_array() returns both named keys and numeric index keys for the same row, which uses more memory and is rarely needed. For beginners, mysqli_fetch_assoc() is simpler and is the better default.

Do I need a WHERE clause to select data in PHP?+

No. Leaving out WHERE returns every row in the table, which is fine for small lookup tables or admin pages. Add a WHERE clause with a prepared statement whenever you want to filter results, such as showing one user's own data.

How do I select only specific columns instead of all columns?+

List the column names after SELECT instead of using the asterisk, for example SELECT name, email FROM students. This returns only those fields in each row, which keeps your result sets smaller and your code clearer about what data it expects.

Is mysqli or PDO better for beginners learning to select data?+

Both work well and both support prepared statements. mysqli is slightly simpler to learn first because its function names describe exactly what they do, like mysqli_fetch_assoc(). PDO becomes useful once you need to support more than one database type in the same project.

Why use a prepared statement instead of just inserting a variable into the query string?+

Inserting a variable directly into a SQL string lets an attacker submit input like "5 OR 1=1" to trick your query into returning data it should not. A prepared statement keeps the query structure and the value completely separate, so user input can never change what the query does.

Building something more than a tutorial project? Our team can help you design and ship a production-ready PHP application.

Talk to us

Get new posts in your inbox

Occasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.

Keep reading

Related posts

All posts

Let's build something

Ready to ship your next product with Fepiq?

Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.