Tổng hợp làm việc với MySQL bằng PHP

Tổng hợp làm việc với MySQL bằng PHP

Tổng hợp kiến thức làm việc với MySQL bằng PHP từ cơ bản đến nâng cao: kết nối cơ sở dữ liệu, CRUD, JOIN, Prepared Statement, Transaction, phân trang, tối ưu truy vấn, bảo mật và kinh nghiệm thực tế, chi tiết như nào hãy cùng chúng tôi phân tích:

MySQL và PHP là bộ đôi được sử dụng rất phổ biến trong quá trình phát triển website. Hầu hết các hệ thống từ blog cá nhân, website doanh nghiệp, trang thương mại điện tử cho đến các phần mềm quản lý đều cần lưu trữ dữ liệu, truy vấn và xử lý thông tin từ cơ sở dữ liệu. Việc nắm vững cách làm việc giữa PHP và MySQL không chỉ giúp lập trình viên xây dựng ứng dụng nhanh hơn mà còn góp phần nâng cao hiệu suất, bảo mật và khả năng mở rộng của hệ thống.

Bài viết này tổng hợp đầy đủ kiến thức về cách kết nối, truy vấn, thêm, sửa, xóa dữ liệu, xử lý lỗi, tối ưu hiệu năng cũng như những kinh nghiệm thực tế khi làm việc với MySQL trong PHP. Nội dung được trình bày theo hướng dễ hiểu, phù hợp cho cả người mới học và lập trình viên muốn hệ thống lại kiến thức.

Tổng hợp làm việc với MySQL bằng PHP

Vai trò của MySQL trong ứng dụng PHP

PHP là ngôn ngữ xử lý phía máy chủ, còn MySQL đảm nhận nhiệm vụ lưu trữ dữ liệu. Hai thành phần này phối hợp với nhau để tạo nên những website có khả năng quản lý dữ liệu động.

Ví dụ, khi người dùng đăng nhập vào website, PHP sẽ nhận dữ liệu từ biểu mẫu, gửi truy vấn đến MySQL để kiểm tra tài khoản. Sau khi MySQL trả kết quả, PHP tiếp tục xử lý và phản hồi cho người dùng.

Quy trình này diễn ra rất nhanh và được lặp lại hàng nghìn hoặc hàng triệu lần trên các hệ thống lớn.

Những dữ liệu thường được lưu trong MySQL

  • Thông tin tài khoản người dùng.
  • Bài viết và chuyên mục.
  • Sản phẩm.
  • Đơn hàng.
  • Bình luận.
  • Danh sách khách hàng.
  • Cấu hình website.
  • Nhật ký hoạt động.

Các phương thức kết nối cơ sở dữ liệu

PHP hỗ trợ nhiều cách làm việc với MySQL, tuy nhiên hiện nay chỉ nên sử dụng MySQLi hoặc PDO. Extension mysql cũ đã bị loại bỏ từ nhiều năm trước và không còn được hỗ trợ.

Phương thức Khuyến nghị Đặc điểm
MySQLi Nên sử dụng Dễ học, tốc độ tốt, hỗ trợ Prepared Statement.
PDO Rất nên sử dụng Hỗ trợ nhiều hệ quản trị cơ sở dữ liệu khác nhau.
mysql Không nên Đã bị loại bỏ khỏi PHP.

Thông tin cần chuẩn bị trước khi kết nối

Để PHP có thể giao tiếp với MySQL cần chuẩn bị đầy đủ các thông tin sau.

  • Tên máy chủ cơ sở dữ liệu.
  • Tên cơ sở dữ liệu.
  • Tài khoản truy cập.
  • Mật khẩu.
  • Cổng kết nối nếu sử dụng cổng khác mặc định.

Trong môi trường localhost, máy chủ thường là localhost hoặc 127.0.0.1. Khi triển khai lên hosting hoặc VPS, các thông số này sẽ được nhà cung cấp dịch vụ cấp sẵn.

Kết nối MySQL bằng MySQLi

Đây là cách phổ biến nhất đối với các dự án PHP truyền thống.

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

$conn = new mysqli($host, $user, $password, $database);

if ($conn->connect_error) {
    die("Kết nối thất bại");
}

echo "Kết nối thành công";
?>

Đoạn mã trên khởi tạo một đối tượng MySQLi và kiểm tra xem quá trình kết nối có xảy ra lỗi hay không.

Đóng kết nối sau khi hoàn thành

Việc đóng kết nối giúp giải phóng tài nguyên trên máy chủ, đặc biệt đối với các ứng dụng có lượng truy cập lớn.

<?php
$conn->close();
?>

Kết nối bằng PDO

PDO là lựa chọn được nhiều lập trình viên yêu thích vì khả năng hỗ trợ nhiều hệ quản trị cơ sở dữ liệu như MySQL, PostgreSQL, SQLite hay SQL Server.

<?php
$dsn = "mysql:host=localhost;dbname=demo;charset=utf8mb4";

try {
    $pdo = new PDO($dsn, "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Không thể kết nối");
}
?>

PDO có cú pháp rõ ràng, hỗ trợ ngoại lệ và rất thuận tiện khi xây dựng các dự án lớn.

Lựa chọn bộ mã hóa ký tự phù hợp

Một trong những lỗi phổ biến nhất khi làm việc với MySQL là dữ liệu tiếng Việt bị lỗi font. Để tránh tình trạng này nên sử dụng bộ mã hóa utf8mb4 cho cả cơ sở dữ liệu, bảng dữ liệu và kết nối.

<?php
$conn->set_charset("utf8mb4");
?>

Ngoài việc thiết lập trong PHP, cơ sở dữ liệu cũng nên được tạo với collation phù hợp để đảm bảo dữ liệu luôn hiển thị chính xác.

Kiểm tra kết nối an toàn

Không nên hiển thị trực tiếp thông báo lỗi của MySQL ra ngoài trình duyệt trong môi trường thực tế vì có thể làm lộ thông tin hệ thống. Thay vào đó nên ghi lỗi vào log và chỉ hiển thị thông báo chung cho người dùng.

Trong môi trường phát triển có thể bật chế độ hiển thị lỗi để dễ kiểm tra. Khi đưa website vào hoạt động chính thức nên tắt hiển thị lỗi và lưu nhật ký để đảm bảo an toàn.

Những lỗi phổ biến khi mới làm việc với MySQL trong PHP

  • Sai tên cơ sở dữ liệu.
  • Nhập sai tài khoản hoặc mật khẩu.
  • Máy chủ MySQL chưa khởi động.
  • Không đặt đúng charset.
  • Sử dụng extension mysql đã lỗi thời.
  • Thiếu quyền truy cập cơ sở dữ liệu.
  • Kết nối thành công nhưng truy vấn sai tên bảng.

Việc hiểu rõ nguyên nhân của từng lỗi sẽ giúp quá trình phát triển website nhanh hơn và hạn chế thời gian dò tìm sự cố.

Định hướng cho các thao tác tiếp theo

Sau khi kết nối thành công với MySQL, bước tiếp theo là thực hiện các thao tác với dữ liệu như truy vấn, thêm bản ghi, cập nhật, xóa, tìm kiếm, phân trang, sử dụng Prepared Statement, Transaction, Join, Index, tối ưu hiệu suất và các kỹ thuật bảo mật khi làm việc với cơ sở dữ liệu. Đây cũng là những nội dung quan trọng quyết định chất lượng của một ứng dụng PHP trong thực tế.

Thực hiện truy vấn lấy dữ liệu

Sau khi kết nối thành công với cơ sở dữ liệu, thao tác được sử dụng nhiều nhất là truy vấn để lấy thông tin. Tùy theo mục đích, câu lệnh SQL có thể lấy toàn bộ dữ liệu hoặc chỉ lấy những bản ghi thỏa mãn điều kiện.

Trong MySQLi, phương thức query() thường được sử dụng để gửi câu lệnh SQL đến máy chủ MySQL.

<?php
$sql = "SELECT * FROM users";
$result = $conn->query($sql);
?>

Nếu truy vấn thành công, biến $result sẽ chứa tập kết quả để tiếp tục xử lý.

Duyệt từng bản ghi

Kết quả trả về thường được đọc theo từng dòng bằng phương thức fetch_assoc(). Phương thức này trả về một mảng kết hợp, trong đó tên cột chính là khóa của mảng.

<?php
while ($row = $result->fetch_assoc()) {
    echo $row["name"];
}
?>

Đây là cách phổ biến nhất khi hiển thị danh sách sản phẩm, bài viết hoặc thành viên trên website.

Lấy một bản ghi duy nhất

Khi truy vấn chỉ trả về một kết quả, có thể đọc trực tiếp mà không cần sử dụng vòng lặp.

<?php
$sql = "SELECT * FROM users WHERE id = 1";
$result = $conn->query($sql);

$user = $result->fetch_assoc();

echo $user["name"];
?>

Đếm số lượng bản ghi

Nhiều chức năng cần biết có bao nhiêu dữ liệu được trả về trước khi xử lý tiếp.

<?php
echo $result->num_rows;
?>

Việc kiểm tra số lượng bản ghi giúp tránh xử lý trên tập dữ liệu rỗng.

<?php
if ($result->num_rows > 0) {

    while ($row = $result->fetch_assoc()) {
        echo $row["name"];
    }

} else {

    echo "Không có dữ liệu.";

}
?>

Thêm dữ liệu mới vào bảng

Câu lệnh INSERT được sử dụng khi cần tạo thêm dữ liệu mới. Đây là thao tác thường gặp trong chức năng đăng ký thành viên, thêm sản phẩm, đăng bài viết hoặc lưu đơn hàng.

<?php
$sql = "INSERT INTO users(name,email)
VALUES('Nguyen Van A','a@example.com')";

$conn->query($sql);
?>

Sau khi thêm thành công, MySQL sẽ tạo thêm một bản ghi mới trong bảng.

Lấy ID vừa được tạo

Nếu bảng sử dụng AUTO_INCREMENT, PHP có thể lấy ngay ID của bản ghi vừa thêm.

<?php
echo $conn->insert_id;
?>

Tính năng này rất hữu ích khi cần lưu dữ liệu liên quan ở các bảng khác.

Cập nhật dữ liệu

Khi cần thay đổi thông tin đã lưu, sử dụng câu lệnh UPDATE. Đây là thao tác thường gặp trong chức năng chỉnh sửa hồ sơ, cập nhật sản phẩm hoặc thay đổi trạng thái đơn hàng.

<?php
$sql = "UPDATE users
SET name='Tran Van B'
WHERE id=1";

$conn->query($sql);
?>

Khi sử dụng UPDATE, luôn cần có điều kiện WHERE để tránh cập nhật toàn bộ dữ liệu trong bảng.

Kiểm tra số bản ghi bị ảnh hưởng

<?php
echo $conn->affected_rows;
?>

Nếu kết quả lớn hơn 0 nghĩa là đã có dữ liệu được thay đổi.

Xóa dữ liệu

DELETE được sử dụng để loại bỏ những bản ghi không còn cần thiết.

<?php
$sql = "DELETE FROM users
WHERE id=5";

$conn->query($sql);
?>

Nên hạn chế xóa trực tiếp đối với các dữ liệu quan trọng. Trong nhiều hệ thống thực tế, lập trình viên thường sử dụng trạng thái kích hoạt thay vì xóa vật lý để có thể khôi phục khi cần.

Cẩn thận khi thiếu điều kiện WHERE

Một lỗi khá phổ biến là quên điều kiện WHERE.

<?php
DELETE FROM users;
?>

Câu lệnh trên sẽ xóa toàn bộ dữ liệu trong bảng. Đây là lỗi rất nghiêm trọng và cần đặc biệt tránh trong quá trình phát triển.

Sử dụng điều kiện WHERE

WHERE giúp giới hạn dữ liệu cần xử lý. Thay vì lấy toàn bộ bảng, chỉ những bản ghi thỏa mãn điều kiện mới được trả về.

<?php
$sql = "SELECT *
FROM users
WHERE status = 1";
?>

Có thể kết hợp nhiều điều kiện để tăng độ chính xác của truy vấn.

<?php
$sql = "SELECT *
FROM users
WHERE status = 1
AND age >= 18";
?>

Sắp xếp dữ liệu với ORDER BY

ORDER BY giúp thay đổi thứ tự hiển thị dữ liệu.

Câu lệnh Ý nghĩa
ASC Sắp xếp tăng dần.
DESC Sắp xếp giảm dần.
<?php
$sql = "SELECT *
FROM users
ORDER BY name ASC";
?>

Hoặc hiển thị bài viết mới nhất.

<?php
$sql = "SELECT *
FROM posts
ORDER BY id DESC";
?>

Giới hạn số lượng bản ghi với LIMIT

Không nên lấy toàn bộ dữ liệu nếu bảng có hàng chục nghìn bản ghi. LIMIT giúp giảm lượng dữ liệu trả về, cải thiện tốc độ truy vấn.

<?php
$sql = "SELECT *
FROM posts
LIMIT 10";
?>

Có thể kết hợp với OFFSET để xây dựng chức năng phân trang.

<?php
$sql = "SELECT *
FROM posts
LIMIT 20 OFFSET 40";
?>

Tìm kiếm dữ liệu bằng LIKE

LIKE được sử dụng khi cần tìm kiếm theo từ khóa.

<?php
$sql = "SELECT *
FROM products
WHERE name LIKE '%Laptop%'";
?>

Dấu phần trăm đại diện cho chuỗi ký tự bất kỳ. Đây là kỹ thuật thường được sử dụng trong chức năng tìm kiếm sản phẩm hoặc bài viết.

Sử dụng IN để lọc nhiều giá trị

Khi cần lấy nhiều giá trị cùng lúc, IN sẽ giúp câu lệnh ngắn gọn và dễ đọc hơn.

<?php
$sql = "SELECT *
FROM orders
WHERE status IN (1,2,3)";
?>

Thay vì viết nhiều điều kiện OR, IN giúp câu lệnh rõ ràng và dễ bảo trì hơn.

Lọc dữ liệu theo khoảng với BETWEEN

BETWEEN thường được dùng khi lọc theo giá tiền, ngày tháng hoặc điểm số.

<?php
$sql = "SELECT *
FROM products
WHERE price BETWEEN 1000000 AND 5000000";
?>

Câu lệnh trên sẽ lấy các sản phẩm có giá nằm trong khoảng từ một triệu đến năm triệu đồng.

Kết hợp nhiều điều kiện

Trong thực tế, truy vấn thường kết hợp nhiều điều kiện để đáp ứng yêu cầu nghiệp vụ.

<?php
$sql = "SELECT *
FROM products
WHERE category_id = 2
AND status = 1
ORDER BY created_at DESC
LIMIT 12";
?>

Đây là kiểu truy vấn thường gặp khi hiển thị danh sách sản phẩm theo danh mục trên các website bán hàng, giúp dữ liệu được lọc chính xác, sắp xếp hợp lý và chỉ lấy số lượng bản ghi cần thiết để tối ưu hiệu năng.

Kết hợp dữ liệu từ nhiều bảng bằng JOIN

Trong hầu hết các ứng dụng thực tế, dữ liệu không được lưu trong một bảng duy nhất mà được tách thành nhiều bảng để giảm trùng lặp và dễ quản lý. Khi cần lấy thông tin liên quan giữa các bảng, JOIN là kỹ thuật quan trọng cần nắm vững.

Ví dụ, bảng orders chỉ lưu mã khách hàng, còn thông tin chi tiết khách hàng được lưu trong bảng users. JOIN sẽ giúp lấy đầy đủ dữ liệu trong một lần truy vấn.

INNER JOIN

INNER JOIN chỉ trả về những bản ghi có dữ liệu tương ứng ở cả hai bảng.

<?php
$sql = "
SELECT orders.id,
       users.name,
       orders.total
FROM orders
INNER JOIN users
ON orders.user_id = users.id
";

$result = $conn->query($sql);
?>

LEFT JOIN

LEFT JOIN luôn lấy toàn bộ dữ liệu của bảng bên trái, ngay cả khi bảng bên phải không có dữ liệu tương ứng.

<?php
$sql = "
SELECT users.name,
       orders.id
FROM users
LEFT JOIN orders
ON users.id = orders.user_id
";
?>

LEFT JOIN thường được sử dụng khi cần thống kê danh sách khách hàng, kể cả những người chưa từng đặt hàng.

Nhóm dữ liệu với GROUP BY

GROUP BY được sử dụng để gom các bản ghi có cùng giá trị thành từng nhóm. Đây là câu lệnh rất hữu ích khi thống kê dữ liệu.

<?php
$sql = "
SELECT category_id,
COUNT(*) AS total
FROM products
GROUP BY category_id
";
?>

Kết quả trả về sẽ cho biết mỗi danh mục đang có bao nhiêu sản phẩm.

Kết hợp GROUP BY với HAVING

HAVING giúp lọc kết quả sau khi dữ liệu đã được nhóm.

<?php
$sql = "
SELECT category_id,
COUNT(*) AS total
FROM products
GROUP BY category_id
HAVING total > 10
";
?>

Ví dụ trên chỉ lấy những danh mục có nhiều hơn mười sản phẩm.

Sử dụng các hàm thống kê

MySQL cung cấp nhiều hàm giúp tính toán trực tiếp trên dữ liệu mà không cần xử lý bằng PHP.

Hàm Mục đích
COUNT() Đếm số bản ghi.
SUM() Tính tổng.
AVG() Tính giá trị trung bình.
MIN() Lấy giá trị nhỏ nhất.
MAX() Lấy giá trị lớn nhất.
<?php
$sql = "
SELECT
COUNT(*) AS total_user,
MAX(age) AS max_age,
MIN(age) AS min_age,
AVG(age) AS average_age
FROM users
";
?>

Prepared Statement giúp chống SQL Injection

Một trong những lỗi bảo mật nguy hiểm nhất khi làm việc với MySQL là SQL Injection. Nguyên nhân thường do nối trực tiếp dữ liệu người dùng vào câu lệnh SQL.

Ví dụ dưới đây là cách viết không an toàn.

<?php
$username = $_POST["username"];

$sql = "SELECT * FROM users
WHERE username = '$username'";
?>

Nếu người dùng nhập dữ liệu độc hại, toàn bộ câu lệnh SQL có thể bị thay đổi.

Cách viết an toàn bằng Prepared Statement

<?php
$stmt = $conn->prepare(
"SELECT * FROM users
WHERE username = ?"
);

$stmt->bind_param("s", $username);

$stmt->execute();

$result = $stmt->get_result();
?>

Prepared Statement giúp tách dữ liệu khỏi câu lệnh SQL nên gần như loại bỏ được nguy cơ SQL Injection nếu sử dụng đúng cách.

Prepared Statement với INSERT

Kỹ thuật này cũng nên áp dụng khi thêm dữ liệu mới.

<?php
$stmt = $conn->prepare(
"INSERT INTO users(name,email)
VALUES(?, ?)"
);

$stmt->bind_param(
"ss",
$name,
$email
);

$stmt->execute();
?>

Không chỉ an toàn hơn mà đoạn mã còn dễ tái sử dụng nhiều lần.

Prepared Statement với UPDATE

<?php
$stmt = $conn->prepare(
"UPDATE users
SET email = ?
WHERE id = ?"
);

$stmt->bind_param(
"si",
$email,
$id
);

$stmt->execute();
?>

Prepared Statement với DELETE

<?php
$stmt = $conn->prepare(
"DELETE FROM users
WHERE id = ?"
);

$stmt->bind_param(
"i",
$id
);

$stmt->execute();
?>

Ý nghĩa của bind_param()

Tham số đầu tiên của bind_param() cho biết kiểu dữ liệu sẽ truyền vào.

Ký tự Kiểu dữ liệu
i Số nguyên.
d Số thực.
s Chuỗi.
b Dữ liệu nhị phân.

Việc khai báo đúng kiểu dữ liệu giúp MySQL xử lý chính xác và tối ưu hơn.

Thực hiện Transaction

Transaction được sử dụng khi nhiều câu lệnh SQL phải thành công đồng thời. Nếu một bước xảy ra lỗi, toàn bộ thay đổi sẽ được hủy bỏ.

Đây là kỹ thuật rất quan trọng trong các hệ thống thanh toán, ngân hàng hoặc quản lý đơn hàng.

<?php
$conn->begin_transaction();

try {

    $conn->query(
    "UPDATE accounts
    SET balance = balance - 100
    WHERE id = 1"
    );

    $conn->query(
    "UPDATE accounts
    SET balance = balance + 100
    WHERE id = 2"
    );

    $conn->commit();

} catch (Exception $e) {

    $conn->rollback();

}
?>

Nếu một trong hai câu lệnh cập nhật thất bại, dữ liệu sẽ quay về trạng thái ban đầu.

Kiểm tra lỗi truy vấn

Trong quá trình phát triển, việc kiểm tra lỗi giúp phát hiện nhanh các vấn đề liên quan đến SQL.

<?php
if (!$conn->query($sql)) {

    echo $conn->error;

}
?>

Khi đưa website vào môi trường thực tế, nên ghi lỗi vào file nhật ký thay vì hiển thị trực tiếp để tránh lộ cấu trúc cơ sở dữ liệu.

Giải phóng bộ nhớ sau khi truy vấn

Sau khi xử lý xong tập kết quả lớn, nên giải phóng bộ nhớ để giảm tài nguyên sử dụng.

<?php
$result->free();
?>

Đây là thói quen tốt khi làm việc với các bảng có số lượng bản ghi lớn hoặc các trang thống kê phức tạp.

Khi nào nên sử dụng MySQLi và khi nào nên dùng PDO

Nếu dự án chỉ sử dụng MySQL và cần cú pháp đơn giản, MySQLi là lựa chọn phù hợp. Trong khi đó, PDO thích hợp với các dự án có khả năng chuyển đổi sang hệ quản trị cơ sở dữ liệu khác hoặc cần cách xử lý ngoại lệ linh hoạt hơn.

Dù lựa chọn thư viện nào, nguyên tắc quan trọng vẫn là luôn sử dụng Prepared Statement, kiểm tra lỗi cẩn thận và xây dựng câu lệnh SQL rõ ràng để đảm bảo hiệu năng cũng như tính bảo mật của ứng dụng.

Xây dựng chức năng phân trang dữ liệu

Khi bảng dữ liệu có hàng nghìn hoặc hàng triệu bản ghi, việc lấy toàn bộ dữ liệu trong một lần truy vấn sẽ làm tăng thời gian phản hồi và tiêu tốn tài nguyên máy chủ. Phân trang giúp chỉ lấy số lượng bản ghi cần thiết cho từng lần hiển thị.

Ý tưởng cơ bản là xác định trang hiện tại, số bản ghi trên mỗi trang và vị trí bắt đầu lấy dữ liệu.

Tính vị trí bắt đầu

<?php
$page = 1;
$limit = 10;

$offset = ($page - 1) * $limit;
?>

Truy vấn dữ liệu theo từng trang

<?php
$sql = "SELECT *
FROM posts
ORDER BY id DESC
LIMIT $limit OFFSET $offset";

$result = $conn->query($sql);
?>

Việc phân trang giúp website tải nhanh hơn, đồng thời mang lại trải nghiệm tốt hơn cho người dùng.

Đếm tổng số bản ghi

Để biết có bao nhiêu trang, cần đếm tổng số dữ liệu trong bảng.

<?php
$sql = "SELECT COUNT(*) AS total
FROM posts";

$result = $conn->query($sql);

$row = $result->fetch_assoc();

$totalRecord = $row["total"];
?>

Sắp xếp dữ liệu theo nhiều cột

ORDER BY có thể kết hợp nhiều trường để tạo cách sắp xếp phù hợp với yêu cầu thực tế.

<?php
$sql = "
SELECT *
FROM products
ORDER BY category_id ASC,
price DESC
";
?>

Ví dụ trên sẽ sắp xếp theo danh mục trước, sau đó các sản phẩm trong cùng danh mục sẽ được sắp xếp theo giá giảm dần.

Sử dụng DISTINCT để loại bỏ dữ liệu trùng lặp

Trong một số trường hợp chỉ cần lấy những giá trị duy nhất, DISTINCT sẽ giúp loại bỏ các dòng bị lặp.

<?php
$sql = "
SELECT DISTINCT city
FROM users
";
?>

Đây là câu lệnh thường dùng khi lấy danh sách tỉnh thành, quốc gia hoặc danh mục không trùng nhau.

Làm việc với giá trị NULL

Trong MySQL, NULL thể hiện dữ liệu chưa có giá trị. Khi kiểm tra NULL không được sử dụng dấu bằng mà phải dùng IS NULL hoặc IS NOT NULL.

<?php
$sql = "
SELECT *
FROM users
WHERE avatar IS NULL
";
?>

Để lấy những người đã có ảnh đại diện.

<?php
$sql = "
SELECT *
FROM users
WHERE avatar IS NOT NULL
";
?>

Lấy dữ liệu theo khoảng thời gian

Các website quản trị thường cần thống kê dữ liệu theo ngày, tháng hoặc năm.

<?php
$sql = "
SELECT *
FROM orders
WHERE created_at
BETWEEN '2026-01-01'
AND '2026-12-31'
";
?>

Việc lọc dữ liệu theo thời gian rất phổ biến trong các báo cáo doanh thu, thống kê truy cập hoặc lịch sử giao dịch.

Thao tác với dữ liệu ngày tháng

MySQL hỗ trợ nhiều hàm xử lý thời gian giúp giảm lượng công việc phía PHP.

Hàm Mục đích
NOW() Lấy thời gian hiện tại.
CURDATE() Lấy ngày hiện tại.
YEAR() Lấy năm.
MONTH() Lấy tháng.
DAY() Lấy ngày.
<?php
$sql = "
SELECT *
FROM orders
WHERE YEAR(created_at)=2026
";
?>

Tìm kiếm gần đúng bằng LIKE

LIKE hỗ trợ nhiều kiểu tìm kiếm khác nhau.

Cú pháp Ý nghĩa
'abc%' Bắt đầu bằng abc.
'%abc' Kết thúc bằng abc.
'%abc%' Chứa abc.
'a%c' Bắt đầu bằng a và kết thúc bằng c.

Thực hiện tìm kiếm bằng Prepared Statement

Khi dữ liệu tìm kiếm được nhập từ người dùng, nên kết hợp Prepared Statement để đảm bảo an toàn.

<?php
$keyword = "%".$keyword."%";

$stmt = $conn->prepare(
"SELECT *
FROM products
WHERE name LIKE ?"
);

$stmt->bind_param(
"s",
$keyword
);

$stmt->execute();

$result = $stmt->get_result();
?>

Xây dựng chức năng đăng nhập

Đăng nhập là ví dụ điển hình khi làm việc giữa PHP và MySQL.

  1. Người dùng nhập tài khoản và mật khẩu.
  2. PHP nhận dữ liệu từ biểu mẫu.
  3. Prepared Statement truy vấn tài khoản.
  4. So sánh mật khẩu.
  5. Tạo phiên đăng nhập nếu thành công.

Không nên lưu mật khẩu dưới dạng văn bản thuần mà cần sử dụng hàm băm của PHP.

Lưu mật khẩu an toàn

PHP cung cấp các hàm chuyên dụng để mã hóa và xác thực mật khẩu.

Tạo mật khẩu

<?php
$password = password_hash(
"123456",
PASSWORD_DEFAULT
);
?>

Kiểm tra mật khẩu

<?php
if (
password_verify(
$inputPassword,
$passwordHash
)
) {

    echo "Đăng nhập thành công.";

}
?>

Việc sử dụng password_hash()password_verify() giúp tăng đáng kể mức độ an toàn so với việc tự mã hóa bằng MD5 hoặc SHA1.

Upload ảnh và lưu đường dẫn vào MySQL

Thông thường, website chỉ lưu đường dẫn của tệp trong MySQL thay vì lưu trực tiếp nội dung của tệp.

<?php
$image = "uploads/avatar.jpg";

$stmt = $conn->prepare(
"UPDATE users
SET avatar=?
WHERE id=?"
);

$stmt->bind_param(
"si",
$image,
$id
);

$stmt->execute();
?>

Cách làm này giúp cơ sở dữ liệu gọn nhẹ, đồng thời dễ dàng sao lưu và quản lý tệp trên máy chủ.

Thực hiện CRUD hoàn chỉnh

CRUD là viết tắt của bốn thao tác quan trọng nhất trong quản lý dữ liệu.

Thao tác Ý nghĩa
Create Thêm dữ liệu.
Read Đọc dữ liệu.
Update Cập nhật dữ liệu.
Delete Xóa dữ liệu.

Hầu hết mọi hệ thống quản trị nội dung, phần mềm quản lý hay website thương mại điện tử đều được xây dựng dựa trên bốn thao tác cơ bản này. Việc tổ chức mã nguồn hợp lý, kết hợp Prepared Statement và kiểm tra lỗi đầy đủ sẽ giúp chức năng CRUD hoạt động ổn định, dễ bảo trì và đảm bảo an toàn cho dữ liệu.

Tối ưu tốc độ truy vấn MySQL trong PHP

Hiệu năng của một ứng dụng không chỉ phụ thuộc vào PHP mà còn chịu ảnh hưởng rất lớn từ cách thiết kế cơ sở dữ liệu và câu lệnh SQL. Một truy vấn không được tối ưu có thể khiến website phản hồi chậm ngay cả khi máy chủ có cấu hình mạnh.

Việc tối ưu nên được thực hiện ngay từ khi thiết kế hệ thống thay vì chờ đến lúc dữ liệu phát sinh quá lớn.

Chỉ lấy những cột cần thiết

Một sai lầm phổ biến là luôn sử dụng SELECT *. Điều này khiến MySQL phải trả về toàn bộ cột mặc dù ứng dụng chỉ sử dụng một vài trường.

Không nên viết.

<?php
$sql = "
SELECT *
FROM users
";
?>

Nên viết.

<?php
$sql = "
SELECT id,
name,
email
FROM users
";
?>

Việc chỉ lấy các cột cần thiết giúp giảm dung lượng dữ liệu truyền giữa MySQL và PHP.

Luôn có điều kiện khi truy vấn

Nếu bảng chứa hàng triệu bản ghi, việc truy vấn toàn bộ dữ liệu sẽ gây áp lực lớn lên máy chủ.

<?php
$sql = "
SELECT id,
title
FROM posts
WHERE status = 1
";
?>

Sử dụng Index hợp lý

Index là một trong những yếu tố quan trọng nhất quyết định tốc độ truy vấn. Khi một cột thường xuyên được tìm kiếm hoặc dùng để JOIN, nên tạo chỉ mục cho cột đó.

Một số trường thường được tạo Index gồm:

  • ID.
  • Email.
  • Username.
  • Slug.
  • Category ID.
  • User ID.
  • Created At.

Tuy nhiên, không nên tạo quá nhiều Index vì mỗi lần INSERT hoặc UPDATE, MySQL cũng phải cập nhật lại các chỉ mục tương ứng.

Giới hạn dữ liệu trả về

Khi xây dựng trang danh sách, chỉ nên lấy đúng số lượng bản ghi cần hiển thị.

<?php
$sql = "
SELECT id,
title
FROM posts
ORDER BY id DESC
LIMIT 20
";
?>

Không nên lấy hàng nghìn bản ghi rồi mới xử lý bằng PHP.

Tránh truy vấn lặp lại trong vòng lặp

Một lỗi thường gặp là thực hiện truy vấn mới bên trong mỗi lần lặp dữ liệu. Điều này làm tăng rất nhiều số lần giao tiếp với MySQL.

Thay vì thực hiện nhiều truy vấn nhỏ, hãy sử dụng JOIN hoặc lấy toàn bộ dữ liệu cần thiết trong một lần truy vấn.

Sử dụng EXPLAIN để phân tích truy vấn

EXPLAIN là công cụ rất hữu ích giúp phân tích cách MySQL thực hiện một câu lệnh SQL.

<?php
$sql = "
EXPLAIN
SELECT *
FROM products
WHERE category_id = 2
";
?>

Thông qua kết quả EXPLAIN, lập trình viên có thể biết truy vấn đã sử dụng Index hay chưa và phát hiện các điểm cần tối ưu.

Đóng Statement sau khi sử dụng

Khi làm việc với Prepared Statement, nên đóng Statement sau khi hoàn thành để giải phóng tài nguyên.

<?php
$stmt->close();
?>

Đóng kết nối cơ sở dữ liệu

Mặc dù PHP sẽ tự động đóng kết nối khi kết thúc chương trình, việc chủ động đóng kết nối vẫn là một thói quen tốt.

<?php
$conn->close();
?>

Xử lý ngoại lệ khi làm việc với PDO

PDO hỗ trợ cơ chế Exception giúp việc phát hiện lỗi trở nên đơn giản hơn.

<?php
try {

    $stmt = $pdo->query(
    "SELECT * FROM users"
    );

} catch (PDOException $e) {

    echo "Có lỗi xảy ra.";

}
?>

Trong môi trường thực tế, thay vì hiển thị lỗi trực tiếp, nên ghi nội dung lỗi vào hệ thống nhật ký.

Backup cơ sở dữ liệu định kỳ

Dù hệ thống được xây dựng tốt đến đâu, việc sao lưu dữ liệu vẫn là yêu cầu bắt buộc. Một bản sao lưu đầy đủ giúp giảm thiểu rủi ro khi máy chủ gặp sự cố hoặc thao tác nhầm dữ liệu.

Nên xây dựng kế hoạch sao lưu theo chu kỳ phù hợp với tần suất cập nhật dữ liệu của website.

  • Sao lưu hàng ngày đối với website có nhiều giao dịch.
  • Sao lưu hàng tuần đối với website ít thay đổi.
  • Lưu nhiều phiên bản sao lưu.
  • Lưu bản sao trên máy chủ khác.
  • Kiểm tra khả năng khôi phục định kỳ.

Khôi phục dữ liệu khi cần thiết

Việc có bản sao lưu nhưng không kiểm tra khả năng phục hồi cũng tiềm ẩn nhiều rủi ro. Do đó, cần thường xuyên thử nghiệm quy trình khôi phục trên môi trường thử nghiệm trước khi áp dụng cho hệ thống thực tế.

Những lỗi thường gặp khi làm việc với MySQL bằng PHP

Lỗi Nguyên nhân phổ biến
Access denied Sai tài khoản hoặc mật khẩu.
Unknown database Không tồn tại cơ sở dữ liệu.
Table doesn't exist Sai tên bảng.
Unknown column Sai tên cột.
Duplicate entry Trùng khóa duy nhất.
Too many connections Quá nhiều kết nối đến MySQL.

Kinh nghiệm thực tế khi phát triển dự án

  • Luôn sử dụng Prepared Statement với dữ liệu từ người dùng.
  • Không lưu mật khẩu ở dạng văn bản thuần.
  • Thiết lập charset utf8mb4 ngay từ đầu.
  • Thiết kế bảng dữ liệu theo nguyên tắc chuẩn hóa.
  • Đặt tên bảng và cột thống nhất.
  • Sử dụng Transaction với các nghiệp vụ liên quan đến tiền hoặc dữ liệu quan trọng.
  • Tạo Index cho các cột thường xuyên tìm kiếm.
  • Không hiển thị lỗi SQL ra ngoài website.
  • Thường xuyên sao lưu cơ sở dữ liệu.
  • Theo dõi hiệu năng truy vấn để tối ưu kịp thời.

Những nguyên tắc giúp ứng dụng ổn định lâu dài

Khi quy mô dự án ngày càng lớn, số lượng truy cập và dữ liệu tăng lên nhanh chóng, việc viết đúng cú pháp SQL là chưa đủ. Một hệ thống bền vững cần có cấu trúc cơ sở dữ liệu hợp lý, câu lệnh được tối ưu, cơ chế phân quyền rõ ràng và quy trình sao lưu đáng tin cậy.

Bên cạnh đó, việc kết hợp giữa PHP và MySQL nên tuân thủ các nguyên tắc về bảo mật, hạn chế truy vấn dư thừa, sử dụng Prepared Statement cho mọi dữ liệu đầu vào và thường xuyên đánh giá hiệu năng của hệ thống. Những thói quen này sẽ giúp website vận hành ổn định, dễ mở rộng và giảm đáng kể nguy cơ phát sinh lỗi trong quá trình khai thác lâu dài.

Kết luận

Làm việc với MySQL bằng PHP là nền tảng của rất nhiều ứng dụng web hiện nay. Từ những thao tác cơ bản như kết nối cơ sở dữ liệu, truy vấn, thêm, sửa và xóa dữ liệu cho đến các kỹ thuật nâng cao như JOIN, Transaction, Prepared Statement, phân trang, Index hay tối ưu truy vấn đều góp phần tạo nên một hệ thống hoạt động hiệu quả và an toàn.

Thay vì chỉ tập trung vào việc hoàn thành chức năng, lập trình viên nên xây dựng thói quen viết mã rõ ràng, tối ưu câu lệnh SQL, kiểm soát lỗi chặt chẽ và chú trọng đến bảo mật ngay từ đầu. Đây là nền tảng giúp ứng dụng PHP có khả năng mở rộng tốt, đáp ứng lượng truy cập lớn và duy trì hiệu năng ổn định trong quá trình vận hành.

  • 0 Bình luận
Trần Thị Vân | Content Creator Web Mới
Trần Thị Vân
Trần Thị Vân là Content Creator tại Web Mới, phụ trách nghiên cứu, biên soạn nội dung và chia sẻ kiến thức về website, SEO, lập trình cùng các xu hướng công nghệ
Chia sẻ nội dung đánh giá của bạn về Tổng hợp làm việc với MySQL bằng PHP
Email, Điện thoại của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *
Đánh giá của bạn
Tên *
Email
Số điện thoại *
Bình luận, Hỏi đáp
Đăng ký tư vấn thiết kế website
Tìm hiểu 1 năm không bằng lắng nghe 1 câu tư vấn