Câu 1Trong console của khóa học này (SQLite), SELECT LENGTH('phở'); trả về gì?
Hàm ② — Hàm chuỗi (LENGTH / TRIM / REPLACE / UPPER / SUBSTR)
Bài thứ hai trong ba bài về hàm SQL. Bao gồm LENGTH để đếm ký tự, TRIM để cắt khoảng trắng, REPLACE để thay thế, UPPER / LOWER để chuyển chữ hoa-thường, và SUBSTR — tất cả trên tập dữ liệu staff được tải từ CSV.
Dữ liệu dùng trong bài này — bảng staff
Bài thứ hai về hàm tập trung vào hàm chuỗi. Chúng ta sẽ đi qua các hàm bạn sẽ dùng bất cứ khi nào cần làm sạch hoặc biến đổi văn bản lấy từ bảng đang hoạt động: độ dài, cắt khoảng trắng, thay thế, chuyển đổi chữ hoa-thường, và trích xuất chuỗi con.
Tập dữ liệu vẫn là bảng staff như lần trước (10 hàng: name / city / salary, v.v.). Lấy các tên trong cột name làm ngôi sao, bốn bài thực hành bao gồm tính độ dài, thay thế họ, viết hoa, và trích xuất chữ cái đầu.
Độ dài chuỗi — `LENGTH` và `CHAR_LENGTH`
Hàm đo độ dài chuỗi hoạt động khác nhau giữa console của khóa học này (SQLite) và MySQL, nên hãy chú ý:
- Console khóa học này (SQLite): LENGTH(s) trả về số ký tự ('phở' → 3)
- MySQL: LENGTH(s) trả về số byte ('phở' → 5, vì ở chiếm 3 byte trong UTF-8). Để lấy số ký tự, dùng CHAR_LENGTH(s)
Bài này dùng LENGTH() cho các bài thực hành, nhưng việc biết sự khác biệt là quan trọng — văn bản tiếng Việt có dấu thanh điệu hầu như luôn là chuỗi đa byte.
-- 1) Đếm ký tự (trong console của khóa học này, LENGTH trả về số ký tự)
SELECT LENGTH('Alice'); -- 5
SELECT LENGTH('phở'); -- 3 (ở đây), 5 (LENGTH của MySQL = số byte)
-- 2) Sắp xếp theo độ dài cột
SELECT name, LENGTH(name) AS name_len FROM staff
ORDER BY name_len DESC;
-- Tham khảo: trong MySQL, số ký tự là CHAR_LENGTH(s)
-- SELECT CHAR_LENGTH('phở') FROM dual; -- 3
Cắt khoảng trắng và thay thế — `TRIM` và `REPLACE`
Trong các bảng thực tế, bạn sẽ gặp khoảng trắng không mong muốn — «ai đó sao chép-dán với khoảng trắng thừa đầu/cuối», «hệ thống trước khi di chuyển để lại khoảng trắng full-width bên trong dữ liệu», v.v. `TRIM(s)` cắt khoảng trắng ở cả hai đầu chuỗi; LTRIM(s) chỉ cắt bên trái, và RTRIM(s) chỉ cắt bên phải.
`REPLACE(s, tìm, thay)` thay thế mọi xuất hiện của tìm trong s bằng thay. Đây là hàm chủ lực cho chuẩn hóa và di chuyển — «viết tắt họ phổ biến Tanaka thành T. để hiển thị gọn», «đổi phần domain của email sang domain mới», v.v. Kết hợp với UPDATE và bạn có thể viết lại giá trị trực tiếp trong bảng.
-- 1) Cắt khoảng trắng: TRIM / LTRIM / RTRIM
SELECT TRIM(' Hello '); -- 'Hello'
SELECT LTRIM(' Hello '); -- 'Hello '
SELECT RTRIM(' Hello '); -- ' Hello'
-- TRIM trên cột: phát hiện hàng có khoảng trắng bằng chênh lệch độ dài
SELECT name FROM staff
WHERE LENGTH(name) <> LENGTH(TRIM(name));
-- 2) Thay thế: REPLACE
SELECT REPLACE('I LIKE APPLE', 'APPLE', 'BANANA');
-- 'I LIKE BANANA'
-- REPLACE trên cột — viết tắt 'Tanaka' thành 'T.'
SELECT name, REPLACE(name, 'Tanaka', 'T.') AS short_name
FROM staff;
Áp dụng TRIM — kết hợp với UPDATE để sửa văn bản không nhất quán
TRIM không chỉ để đọc — kết hợp với UPDATE, nó có thể viết lại giá trị trực tiếp trong bảng. Ví dụ, để chuẩn hóa hàng loạt cột name có khoảng trắng đầu/cuối thừa, viết kiểu UPDATE staff SET name = TRIM(name) WHERE LENGTH(name) <> LENGTH(TRIM(name)); — mẫu an toàn là lọc trước bằng WHERE, rồi UPDATE. Nếu bỏ WHERE, mỗi hàng đều bị TRIM (gần như vô hại nhưng UPDATE thừa). REPLACE hoạt động tương tự: UPDATE bảng SET cột = REPLACE(cột, 'A', 'B') là kỹ thuật cơ bản để sửa hàng loạt văn bản không nhất quán.
Chuyển đổi chữ hoa-thường và chuỗi con — `UPPER` / `LOWER` / `SUBSTR`
`UPPER(s)` chuyển chuỗi thành tất cả chữ hoa, và `LOWER(s)` thành tất cả chữ thường. Dùng chúng khi bạn muốn điều kiện tìm kiếm không phân biệt chữ hoa-thường (WHERE UPPER(email) = 'X@Y.COM') hoặc định dạng hiển thị nhất quán. Chúng không tác động đến các ký tự không có phân biệt chữ hoa-thường (như tiếng Nhật).
`SUBSTR(s, bắt_đầu, độ_dài)` trích xuất `độ_dài` ký tự bắt đầu từ vị trí `bắt_đầu` (bạn cũng có thể viết là SUBSTRING). Vị trí trong SQL bắt đầu từ 1, nên SUBSTR('Alice Tanaka', 1, 5) trả về 'Alice'. Bỏ đối số thứ ba và nó trả về tất cả đến cuối; truyền bắt_đầu âm như SUBSTR(s, -3) và nó đếm từ cuối.
-- 1) UPPER / LOWER
SELECT UPPER('apple'), LOWER('APPLE');
-- 'APPLE', 'apple'
-- Trên cột: lấy tên ở dạng chữ hoa và chữ thường
SELECT name, UPPER(name) AS upper_name, LOWER(name) AS lower_name
FROM staff;
-- 2) SUBSTR: vị trí là cơ số 1
SELECT SUBSTR('Alice Tanaka', 1, 5); -- 'Alice'
SELECT SUBSTR('Alice Tanaka', 7, 6); -- 'Tanaka'
SELECT SUBSTR('Alice Tanaka', 7); -- 'Tanaka' -- bỏ độ dài → đến cuối
SELECT SUBSTR('Alice Tanaka', -6); -- 'Tanaka' -- âm → từ cuối
-- Ký tự đầu tiên của mỗi tên
SELECT name, SUBSTR(name, 1, 1) AS initial FROM staff;
-- Tham khảo: REVERSE là hàm MySQL / Oracle — không có trong console của khóa học này
-- SELECT REVERSE('Alice Tanaka'); -- 'akanaT ecilA' (hoạt động trong MySQL)
Tìm vị trí của chuỗi con — `INSTR`
`INSTR(đích, tìm)` trả về vị trí (chỉ số cơ số 1) nơi `tìm` xuất hiện đầu tiên trong đích. Vị trí bắt đầu từ 1, và nếu chuỗi tìm kiếm không thấy, nó trả về 0. Ví dụ, INSTR('Alice Tanaka', ' ') trả về 6 vì khoảng trắng ở vị trí thứ 6.
Kết hợp với SUBSTR và bạn có thể cắt chuỗi dựa trên dấu phân cách thay vì vị trí cố định. Đây là combo chủ lực để biến đổi chuỗi có độ dài thay đổi — «tách email quanh @», «trích xuất chỉ họ từ tên đầy đủ», v.v.
-- 1) INSTR đơn — kiểm tra vị trí khoảng trắng
SELECT name, INSTR(name, ' ') AS space_pos FROM staff;
-- 'Alice Tanaka' → 6, 'Bob Suzuki' → 4, ...
-- 2) Kết hợp với SUBSTR để trích xuất họ
SELECT name,
SUBSTR(name, INSTR(name, ' ') + 1) AS last_name
FROM staff;
-- 3) Tách quanh '@' (ví dụ email)
SELECT INSTR('alice@example.com', '@'); -- 6
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2SELECT REPLACE('I LIKE APPLE', 'APPLE', 'BANANA'); trả về gì?
Câu 3SELECT SUBSTR('Alice Tanaka', 7, 6); trả về gì?