SQL cho Tester: những câu lệnh cần biết để kiểm chứng dữ liệu
Giao diện báo "Lưu thành công" không có nghĩa dữ liệu đã được lưu đúng. Tester biết SQL kiểm chứng được điều thực sự xảy ra trong cơ sở dữ liệu — và đó là ranh giới rõ rệt giữa một tester junior và một tester được tin cậy.
Vì sao tester cần biết SQL?
- Kiểm chứng kết quả thật: sau khi thao tác trên giao diện, dữ liệu trong bảng có đúng như kỳ vọng không.
- Chuẩn bị dữ liệu test: tạo nhanh tài khoản, đơn hàng, trạng thái cần thiết thay vì bấm tay hàng chục bước.
- Điều tra bug: xác định lỗi nằm ở tầng giao diện, tầng dịch vụ hay tầng dữ liệu.
- Đối chiếu báo cáo: số liệu trên màn hình báo cáo có khớp với dữ liệu gốc không.
- Tìm lớp lỗi vô hình: dữ liệu mồ côi, giá trị NULL không mong đợi, bản ghi trùng lặp.
SELECT và WHERE — truy vấn cơ bản
-- Kiểm tra một tài khoản vừa đăng ký có được lưu đúng không
SELECT id, email, status, created_at
FROM users
WHERE email = 'test@pinelab.vn';
-- Tìm các đơn hàng đang chờ xử lý quá 24 giờ
SELECT id, customer_id, total, created_at
FROM orders
WHERE status = 'pending'
AND created_at < NOW() - INTERVAL '24 hours'
ORDER BY created_at ASC;Các toán tử WHERE dùng nhiều nhất
| Toán tử | Dùng để | Ví dụ |
|---|---|---|
| =, <>, >, <, >=, <= | So sánh giá trị | status = 'active' |
| IN | Thuộc một tập giá trị | status IN ('pending', 'confirmed') |
| BETWEEN | Nằm trong khoảng | total BETWEEN 100000 AND 500000 |
| LIKE | Khớp mẫu chuỗi | email LIKE '%@pinelab.vn' |
| IS NULL / IS NOT NULL | Kiểm tra giá trị rỗng | deleted_at IS NULL |
| AND / OR / NOT | Kết hợp điều kiện | status = 'paid' AND total > 0 |
JOIN — ghép dữ liệu từ nhiều bảng
Dữ liệu nghiệp vụ gần như không bao giờ nằm gọn trong một bảng. Muốn biết "đơn hàng này của khách nào, gồm sản phẩm gì", bạn phải ghép ít nhất ba bảng.
-- Đối chiếu chi tiết một đơn hàng với thông tin khách và sản phẩm
SELECT
o.id AS order_id,
u.email AS customer_email,
p.name AS product_name,
oi.quantity,
oi.unit_price,
oi.quantity * oi.unit_price AS line_total
FROM orders o
JOIN users u ON u.id = o.customer_id
JOIN order_items oi ON oi.order_id = o.id
JOIN products p ON p.id = oi.product_id
WHERE o.id = 1024;| Loại JOIN | Trả về | Dùng khi kiểm thử |
|---|---|---|
| INNER JOIN | Chỉ các bản ghi khớp ở cả hai bảng | Đối chiếu dữ liệu liên quan chắc chắn tồn tại |
| LEFT JOIN | Toàn bộ bảng trái, kèm khớp bên phải nếu có | Tìm bản ghi thiếu liên kết — cực kỳ hữu ích khi săn dữ liệu mồ côi |
| RIGHT JOIN | Toàn bộ bảng phải, kèm khớp bên trái nếu có | Ít dùng; thường viết lại thành LEFT JOIN cho dễ đọc |
-- Tìm order_items trỏ tới sản phẩm đã bị xoá
SELECT oi.id, oi.order_id, oi.product_id
FROM order_items oi
LEFT JOIN products p ON p.id = oi.product_id
WHERE p.id IS NULL;GROUP BY và hàm tổng hợp — đối chiếu báo cáo
Khi kiểm thử màn hình báo cáo hoặc dashboard, cách duy nhất để biết con số hiển thị có đúng không là tự tính lại từ dữ liệu gốc.
-- Doanh thu theo trạng thái đơn hàng trong tháng 8/2026
SELECT
status,
COUNT(*) AS so_don,
SUM(total) AS doanh_thu,
AVG(total) AS gia_tri_tb,
MIN(total) AS don_nho_nhat,
MAX(total) AS don_lon_nhat
FROM orders
WHERE created_at >= '2026-08-01'
AND created_at < '2026-09-01'
GROUP BY status
ORDER BY doanh_thu DESC;Tìm bản ghi trùng lặp
-- Phát hiện email bị đăng ký trùng — lỗi ràng buộc duy nhất
SELECT email, COUNT(*) AS so_lan
FROM users
GROUP BY email
HAVING COUNT(*) > 1;Nguyên tắc an toàn khi tester chạy SQL
- Yêu cầu quyền chỉ đọc trên production. Đây là biện pháp bảo vệ tốt nhất cho chính bạn.
- Luôn viết SELECT trước để xem chính xác những dòng nào sẽ bị ảnh hưởng, rồi mới đổi thành UPDATE hoặc DELETE nếu thực sự cần.
- Dùng LIMIT khi khám phá dữ liệu trên bảng lớn để tránh làm chậm hệ thống.
- Bọc thao tác thay đổi trong transaction để có thể hoàn tác nếu kết quả không như mong đợi.
- Không sao chép dữ liệu thật của người dùng ra môi trường không được bảo vệ.
-- Cách làm an toàn: xem trước rồi mới sửa
-- Bước 1 — xem chính xác những dòng sẽ bị ảnh hưởng
SELECT id, status FROM orders WHERE customer_id = 42 AND status = 'draft';
-- Bước 2 — chỉ chạy khi kết quả bước 1 đúng như mong đợi
BEGIN;
UPDATE orders SET status = 'cancelled'
WHERE customer_id = 42 AND status = 'draft';
-- Kiểm tra số dòng bị ảnh hưởng, rồi COMMIT hoặc ROLLBACK
ROLLBACK;Lộ trình học SQL trong 3 tuần
| Tuần | Nội dung | Bài tập kiểm chứng |
|---|---|---|
| Tuần 1 | SELECT, WHERE, ORDER BY, LIMIT, các toán tử so sánh, xử lý NULL | Tự tìm được một bản ghi cụ thể theo nhiều điều kiện |
| Tuần 2 | JOIN các loại, khoá chính và khoá ngoại, truy vấn nhiều bảng | Viết được truy vấn ghép 3 bảng và tìm dữ liệu mồ côi |
| Tuần 3 | GROUP BY, hàm tổng hợp, HAVING, truy vấn con | Tự tính lại được một con số trên màn hình báo cáo |
Câu hỏi thường gặp
Tester cần học SQL đến mức nào?
Đủ để đọc và viết truy vấn lấy dữ liệu: SELECT, WHERE, các loại JOIN, GROUP BY và hàm tổng hợp. Tester không cần học tối ưu truy vấn, thiết kế cơ sở dữ liệu hay các thao tác quản trị. Khoảng ba tuần học nghiêm túc là đủ dùng trong công việc hằng ngày.
Tester có được phép sửa dữ liệu trên production không?
Không. Tester chỉ nên có quyền chỉ đọc trên môi trường production. Mọi thao tác thay đổi dữ liệu phải thực hiện trên môi trường test, và nếu bắt buộc phải sửa trên production thì phải thông qua quy trình có phê duyệt và sao lưu.
Vì sao câu lệnh WHERE column = NULL không trả về kết quả?
Vì trong SQL, NULL nghĩa là giá trị chưa biết, và mọi phép so sánh với giá trị chưa biết đều cho kết quả không xác định chứ không phải đúng. Để kiểm tra giá trị rỗng, phải dùng IS NULL hoặc IS NOT NULL.
Học SQL trên hệ quản trị nào thì phù hợp?
PostgreSQL hoặc MySQL là hai lựa chọn phổ biến nhất và cú pháp cơ bản gần như giống nhau. Kiến thức SELECT, JOIN và GROUP BY chuyển đổi được giữa các hệ quản trị, khác biệt chỉ nằm ở các hàm nâng cao và cú pháp xử lý ngày tháng.