Câu lệnh SELECT đầu tiên
Bạn sẽ học được
- Cấu trúc đầy đủ của một câu
SELECTvà thứ tự các mệnh đề. - Chạy
SELECT *để xem toàn bộ bảng, và biết khi nào nên tránh nó. - Vì sao thứ tự dòng trong kết quả không đáng tin nếu thiếu
ORDER BY. - Đọc kết quả trả về như một bảng thật: tên cột, kiểu giá trị, dòng trống.
- Hoàn thành bài luyện đầu tiên: lấy toàn bộ khách hàng theo
id.
Khái niệm cốt lõi
Mọi truy vấn đọc dữ liệu đều xoay quanh SELECT. Cấu trúc đầy đủ của nó, theo đúng thứ tự bạn viết:
SELECT <cột muốn lấy>
FROM <bảng nguồn>
WHERE <điều kiện lọc> -- tuỳ chọn
ORDER BY <cột sắp xếp> -- tuỳ chọn
LIMIT <số dòng tối đa>; -- tuỳ chọnĐiều thú vị: thứ tự bạn viết không phải thứ tự máy thực thi. Máy đọc FROM trước để biết lấy dữ liệu từ đâu, rồi WHERE để lọc, rồi SELECT để chọn cột, rồi ORDER BY, cuối cùng LIMIT. Hiểu thứ tự này sẽ giúp bạn tránh một lỗi rất phổ biến: dùng bí danh vừa đặt trong SELECT ở mệnh đề WHERE. Lúc WHERE chạy, bí danh đó chưa tồn tại.
Kết quả của SELECT là một bảng tạm (result set): có tên cột, có dòng, có kiểu dữ liệu. Bạn có thể tưởng tượng nó như một bảng mới sinh ra trong bộ nhớ. Điều này quan trọng vì nhiều kỹ thuật nâng cao — subquery, CTE, view — chỉ là đặt một result set vào chỗ của một bảng.
Dấu * nghĩa là "mọi cột". Nó tiện khi khám phá, nhưng có ba nhược điểm: kéo về dữ liệu bạn không dùng, không rõ ý định truy vấn, và dễ vỡ khi ai đó thêm cột vào bảng. Quy tắc thực tế: * để xem, danh sách cột để dùng.
Cuối cùng, một sự thật ít người mới biết: SQL không hứa thứ tự dòng nếu bạn không yêu cầu. Cùng một câu SELECT * FROM customers;, hôm nay có thể trả về An trước Bình, mai có thể khác — nhất là khi bảng lớn và có nhiều CPU. Nếu kết quả cần ổn định (báo cáo, so sánh, chấm bài), luôn thêm ORDER BY.
Ví dụ chạy được
Lấy toàn bộ khách hàng:
SELECT *
FROM customers;Kết quả có 12 dòng. Dưới đây là toàn bộ, để bạn thấy dữ liệu thật trông như thế nào:
| id | name | city | signup_date | segment | |
|---|---|---|---|---|---|
| 1 | An Nguyễn | an@example.com | Hà Nội | 2023-03-12 | retail |
| 2 | Bình Trần | binh@example.com | TP. Hồ Chí Minh | 2023-07-01 | vip |
| 3 | Chi Lê | chi@example.com | Đà Nẵng | 2024-01-15 | retail |
| 4 | Dũng Phạm | (NULL) | Hà Nội | 2024-02-20 | wholesale |
| 5 | Em Võ | em@example.com | TP. Hồ Chí Minh | 2024-05-05 | retail |
| 6 | Giang Đặng | giang@example.com | Cần Thơ | 2024-08-18 | vip |
| 7 | Hà Bùi | ha@example.com | Hải Phòng | 2024-11-02 | retail |
| 8 | Inh Đỗ | (NULL) | TP. Hồ Chí Minh | 2025-01-10 | retail |
| 9 | Khánh Hồ | khanh@example.com | Hà Nội | 2025-02-14 | wholesale |
| 10 | Linh Ngô | linh@example.com | Đà Nẵng | 2025-03-09 | retail |
| 11 | Minh Dương | minh@example.com | Cần Thơ | 2025-04-21 | vip |
| 12 | Nga Lý | nga@example.com | TP. Hồ Chí Minh | 2025-06-30 | retail |
Ba điều đáng chú ý trong bảng này:
- Hai khách (Dũng, Inh) không có email — đây là
NULL, không phải chuỗi rỗng. - Cột
signup_datehiển thị dạng2023-03-12(năm-tháng-ngày), chuẩn ISO. Đây là cách an toàn nhất để đọc ngày, tránh nhầm giữa03/12kiểu Mỹ và kiểu Việt. - Cột
segmentphân loại khách:retail,vip,wholesale.
Bây giờ thêm ORDER BY:
SELECT id, name, city
FROM customers
ORDER BY id;Kết quả giống bảng trên nhưng chỉ ba cột và chắc chắn xếp từ id 1 đến 12. Thử đổi thành ORDER BY name; — bạn sẽ thấy thứ tự theo bảng chữ cái. Với tiếng Việt, PostgreSQL sắp xếp theo collation của database, nên đừng ngạc nhiên nếu thứ tự hơi khác so với trực giác: dấu tiếng Việt ảnh hưởng đến vị trí.
Thử một truy vấn có LIMIT:
SELECT id, name
FROM customers
ORDER BY signup_date DESC
LIMIT 3;Kết quả là ba khách đăng ký gần đây nhất: Nga Lý (2025-06-30), Minh Dương (2025-04-21), Linh Ngô (2025-03-09). Lưu ý DESC — sắp xếp giảm dần. Mặc định là ASC (tăng dần). Khi cần "mới nhất", "lớn nhất", "đắt nhất", gần như luôn là DESC.
Thực hành
- Chạy
SELECT * FROM customers;rồiSELECT * FROM customers ORDER BY id;. So sánh thứ tự hai kết quả — trong bộ dữ liệu nhỏ này có thể giống nhau, nhưng hãy tập thói quen thêmORDER BY. - Chạy
SELECT id, name, signup_date FROM customers ORDER BY signup_date DESC LIMIT 5;và xác nhận năm khách mới nhất. - Mở bài luyện Lấy toàn bộ khách hàng (
select-all-customers) và nộp bài. Yêu cầu là trả về mọi cột của mọi khách hàng, sắp xếp theoidtăng dần. Đáp án chính là truy vấn thứ hai trong mục ví dụ, thêmORDER BY id.
Nếu bài luyện báo sai, đừng vội sửa mò. Đọc thông báo: nó thường nói bạn thiếu cột, thừa cột hay sai thứ tự. Với bài này, thứ tự dòng quan trọng vì yêu cầu có ORDER BY id.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
syntax error at end of input | Quên FROM hoặc quên dấu ; | Kiểm tra lại cấu trúc SELECT ... FROM ...; |
| Kết quả đúng dữ liệu nhưng bài luyện báo sai thứ tự | Thiếu ORDER BY id | Yêu cầu có "sắp xếp theo id" thì phải viết ORDER BY id |
SELECT * trả về cột lạ so với tài liệu | Bảng vừa được thêm cột | Không phụ thuộc vào *; liệt kê cột bạn cần |
| Kết quả chỉ có một phần dòng | Còn sót LIMIT từ lần thử trước | Xoá LIMIT hoặc tăng số dòng |
ORDER BY ten báo lỗi không có cột | Dùng tên tiếng Việt thay vì tên cột thật | Xem tên cột bằng SELECT * ... LIMIT 1 |
Tóm tắt
SELECTchọn cột,FROMchọn bảng;WHERE,ORDER BY,LIMITlà tuỳ chọn nhưng cực kỳ thường dùng.- Máy thực thi theo thứ tự
FROM → WHERE → SELECT → ORDER BY → LIMIT, khác thứ tự bạn viết. - Kết quả truy vấn là một bảng tạm có tên cột và kiểu dữ liệu.
- Không có
ORDER BYthì không có thứ tự đảm bảo. SELECT *để khám phá; liệt kê cột khi truy vấn được dùng thật.
Use ← → to move between lessons