Các lệnh SQL cơ bản: SELECT, INSERT, UPDATE, DELETE
Nếu bạn đang học SQL, đây là 4 lệnh bạn sẽ dùng hàng ngày: SELECT (truy vấn), INSERT (thêm), UPDATE (sửa), DELETE (xóa). Bài viết này giải thích từng lệnh với ví dụ thực tế trên bảng sinh viên — bạn có thể chạy thử ngay trên SQLite Online mà không cần cài đặt gì.
Nếu chưa biết SQL là gì, hãy đọc SQL là gì? Hướng dẫn SQL cơ bản từ đầu trước.
Bảng mẫu dùng xuyên suốt bài
Chúng ta sẽ dùng một bảng sinh viên đơn giản. Chạy đoạn SQL sau để tạo dữ liệu mẫu:
-- Tạo bảng sinh viên
CREATE TABLE sinh_vien (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ho_ten TEXT NOT NULL,
tuoi INTEGER,
email TEXT,
nganh TEXT,
diem_tb REAL
);
-- Thêm dữ liệu mẫu
INSERT INTO sinh_vien (ho_ten, tuoi, email, nganh, diem_tb) VALUES
('Nguyễn Văn Minh', 20, 'minh@email.com', 'CNTT', 8.5),
('Trần Thị Lan', 21, 'lan@email.com', 'CNTT', 9.0),
('Lê Hoàng Nam', 19, 'nam@email.com', 'Kinh tế', 7.5),
('Phạm Thị Mai', 22, 'mai@email.com', 'CNTT', 8.0),
('Võ Đức Hùng', 20, 'hung@email.com', 'Marketing', 7.0),
('Nguyễn Thị Hoa', 21, 'hoa@email.com', 'Kinh tế', 8.5),
('Đặng Văn Tùng', 23, 'tung@email.com', 'CNTT', 6.5);
SELECT — Truy vấn dữ liệu
SELECT là lệnh dùng nhiều nhất trong SQL. Nó đọc dữ liệu từ bảng mà không thay đổi gì — an toàn để thực hành.
Cú pháp cơ bản
-- Lấy tất cả cột
SELECT * FROM sinh_vien;
-- Chỉ lấy các cột cần thiết (khuyến nghị dùng trong thực tế)
SELECT ho_ten, nganh, diem_tb FROM sinh_vien;
Mẹo thực tế: Tránh dùng SELECT * trong code production. Chỉ chọn đúng cột bạn cần — vừa nhanh hơn, vừa dễ bảo trì.
WHERE — Lọc theo điều kiện
WHERE giúp lọc ra những hàng thỏa điều kiện. Đây là phần quan trọng nhất của SELECT.
-- Lọc theo ngành học
SELECT * FROM sinh_vien WHERE nganh = 'CNTT';
-- Lọc theo điểm số
SELECT * FROM sinh_vien WHERE diem_tb >= 8.0;
-- Kết hợp nhiều điều kiện với AND / OR
SELECT * FROM sinh_vien WHERE nganh = 'CNTT' AND diem_tb >= 8.0;
SELECT * FROM sinh_vien WHERE nganh = 'CNTT' OR nganh = 'Marketing';
-- Tìm kiếm gần đúng với LIKE (% là ký tự đại diện)
SELECT * FROM sinh_vien WHERE ho_ten LIKE '%Nguyễn%';
-- Lọc trong khoảng giá trị
SELECT * FROM sinh_vien WHERE tuoi BETWEEN 20 AND 22;
-- Lọc theo danh sách giá trị
SELECT * FROM sinh_vien WHERE nganh IN ('CNTT', 'Marketing');
ORDER BY — Sắp xếp kết quả
-- Sắp xếp điểm từ cao xuống thấp
SELECT ho_ten, diem_tb FROM sinh_vien ORDER BY diem_tb DESC;
-- Sắp xếp tên theo thứ tự bảng chữ cái
SELECT ho_ten, nganh FROM sinh_vien ORDER BY ho_ten ASC;
LIMIT và DISTINCT
-- Top 3 sinh viên điểm cao nhất
SELECT ho_ten, diem_tb FROM sinh_vien ORDER BY diem_tb DESC LIMIT 3;
-- Lấy danh sách ngành học không trùng lặp
SELECT DISTINCT nganh FROM sinh_vien;
INSERT — Thêm dữ liệu mới
INSERT thêm một hoặc nhiều hàng mới vào bảng. Luôn chỉ rõ tên cột — đừng dựa vào thứ tự cột mặc định.
-- Thêm một sinh viên
INSERT INTO sinh_vien (ho_ten, tuoi, email, nganh, diem_tb)
VALUES ('Bùi Văn Long', 20, 'long@email.com', 'CNTT', 7.5);
-- Thêm nhiều sinh viên cùng lúc (hiệu quả hơn nhiều câu INSERT riêng lẻ)
INSERT INTO sinh_vien (ho_ten, tuoi, email, nganh, diem_tb) VALUES
('Hoàng Thị Thảo', 19, 'thao@email.com', 'Marketing', 8.0),
('Phan Đức Anh', 22, 'anh@email.com', 'Kinh tế', 7.0);
Lỗi thường gặp với INSERT:
- Không chỉ rõ tên cột — dễ bị lỗi nếu cấu trúc bảng thay đổi
- Chèn giá trị trùng khóa chính (PRIMARY KEY) — sẽ báo lỗi constraint
- Bỏ qua cột NOT NULL mà không có giá trị mặc định — sẽ báo lỗi
UPDATE — Cập nhật dữ liệu
UPDATE sửa dữ liệu đã có trong bảng. Cảnh báo quan trọng: luôn dùng WHERE để chỉ định hàng cần sửa — nếu quên WHERE, toàn bộ bảng sẽ bị cập nhật.
-- Cập nhật email của một sinh viên cụ thể
UPDATE sinh_vien
SET email = 'minh.nguyen@gmail.com'
WHERE ho_ten = 'Nguyễn Văn Minh';
-- Cập nhật nhiều cột cùng lúc
UPDATE sinh_vien
SET email = 'lan.tran@gmail.com', diem_tb = 9.2
WHERE id = 2;
-- ⚠ NGUY HIỂM — KHÔNG BAO GIỜ LÀM THẾ NÀY:
-- UPDATE sinh_vien SET diem_tb = 0;
-- Câu lệnh trên sẽ đặt điểm tất cả sinh viên thành 0!
Thói quen tốt: Trước khi UPDATE, hãy chạy câu SELECT với điều kiện WHERE tương tự để xem đúng bao nhiêu hàng bị ảnh hưởng:
-- Kiểm tra trước
SELECT * FROM sinh_vien WHERE ho_ten = 'Nguyễn Văn Minh';
-- Sau khi xác nhận đúng, mới chạy UPDATE
UPDATE sinh_vien
SET email = 'minh.nguyen@gmail.com'
WHERE ho_ten = 'Nguyễn Văn Minh';
DELETE — Xóa dữ liệu
DELETE xóa hàng khỏi bảng. Cũng như UPDATE, luôn dùng WHERE — DELETE không có WHERE sẽ xóa toàn bộ dữ liệu trong bảng.
-- Xóa sinh viên theo ID (an toàn nhất vì ID là duy nhất)
DELETE FROM sinh_vien WHERE id = 7;
-- Xóa tất cả sinh viên ngành Marketing có điểm dưới 7.0
DELETE FROM sinh_vien WHERE nganh = 'Marketing' AND diem_tb < 7.0;
-- ⚠ NGUY HIỂM — KHÔNG BAO GIỜ LÀM THẾ NÀY:
-- DELETE FROM sinh_vien;
-- Câu lệnh trên sẽ xóa TOÀN BỘ dữ liệu trong bảng!
Lưu ý: DELETE xóa hàng nhưng không xóa bảng. Nếu muốn xóa cấu trúc bảng, dùng DROP TABLE. Nếu muốn xóa hết dữ liệu nhưng giữ bảng, có thể dùng TRUNCATE TABLE sinh_vien (nhanh hơn DELETE không có WHERE).
Hàm tổng hợp và GROUP BY
Sau khi nắm SELECT cơ bản, bạn sẽ cần tính toán trên nhóm dữ liệu — đây là lúc dùng hàm tổng hợp kết hợp GROUP BY.
Hàm tổng hợp (Aggregate Functions)
SELECT COUNT(*) AS tong_sinh_vien FROM sinh_vien;
SELECT AVG(diem_tb) AS diem_trung_binh FROM sinh_vien;
SELECT MAX(diem_tb) AS diem_cao_nhat FROM sinh_vien;
SELECT MIN(diem_tb) AS diem_thap_nhat FROM sinh_vien;
SELECT SUM(diem_tb) AS tong_diem FROM sinh_vien;
GROUP BY — Nhóm và thống kê theo danh mục
-- Đếm số sinh viên mỗi ngành
SELECT nganh, COUNT(*) AS so_luong
FROM sinh_vien
GROUP BY nganh;
-- Tính điểm trung bình từng ngành
SELECT nganh, AVG(diem_tb) AS diem_tb_nganh
FROM sinh_vien
GROUP BY nganh
ORDER BY diem_tb_nganh DESC;
-- HAVING: lọc nhóm sau khi GROUP BY (khác với WHERE lọc từng hàng)
SELECT nganh, AVG(diem_tb) AS diem_tb_nganh
FROM sinh_vien
GROUP BY nganh
HAVING AVG(diem_tb) >= 8.0;
WHERE vs HAVING: WHERE lọc từng hàng trước khi nhóm. HAVING lọc các nhóm sau khi GROUP BY. Không thể dùng HAVING thay WHERE cho điều kiện thông thường.
Câu hỏi thường gặp
Làm sao kiểm tra giá trị NULL?
Dùng IS NULL hoặc IS NOT NULL — không dùng = NULL vì trong SQL, NULL không bằng bất cứ thứ gì kể cả chính nó.
-- Tìm sinh viên chưa có email
SELECT * FROM sinh_vien WHERE email IS NULL;
-- Tìm sinh viên đã có email
SELECT * FROM sinh_vien WHERE email IS NOT NULL;
Lệnh SQL có phân biệt hoa thường không?
Từ khóa SQL như SELECT, FROM, WHERE không phân biệt hoa thường. Nhưng giá trị dữ liệu (ví dụ: 'CNTT' khác 'cntt') thì tùy thuộc vào hệ quản trị cơ sở dữ liệu và cấu hình collation.
Có thể kết hợp WHERE với ORDER BY và LIMIT không?
Có. Thứ tự các mệnh đề: SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT.
Bước tiếp theo
Sau khi nắm vững 4 lệnh cơ bản này, bước tiếp theo là học cách kết hợp nhiều bảng:
- JOIN trong SQL: INNER JOIN, LEFT JOIN, RIGHT JOIN — kỹ năng quan trọng nhất khi làm việc với database thực tế
- SQL là gì? — ôn lại nền tảng nếu cần