Vấn đề: Tìm kiếm giá trị trong danh sách phân cách bởi dấu phẩy
Khi một cột lưu trữ nhiều giá trị dưới dạng chuỗi phân cách bằng dấu phẩy (ví dụ: 'MongoDB,Java,Python'), việc tìm kiếm một giá trị cụ thể (như 'MySQL') không thể dùng = hoặc LIKE '%MySQL%' đơn giản vì dễ khớp sai (ví dụ: 'MySQLite').
Giải pháp: Sử dụng REGEXP với ranh giới từ
Biểu thức chính quy REGEXP cho phép khớp chính xác giá trị giữa các dấu phẩy hoặc ở đầu/cuối chuỗi.
1. Tạo bảng và dữ liệu
CREATE TABLE DemoTable (
Subjects TEXT
);
INSERT INTO DemoTable VALUES
('MongoDB,Java,Python'),
('SQL Server,MySQL,PL/SQL'),
('Hibernate,Spring,JPA');
2. Truy vấn tìm 'MySQL' chính xác
SELECT * FROM DemoTable
WHERE Subjects REGEXP '(^|.*,)MySQL(,.*|$)';
3. Giải thích regex
(^|.*,)– Khớp đầu chuỗi (^) HOẶC bất kỳ ký tự nào kết thúc bằng dấu phẩy (.*,). Đảm bảo 'MySQL' ở đầu hoặc sau dấu phẩy.MySQL– Giá trị cần tìm.(,.*|$)– Khớp dấu phẩy theo sau (,.*) HOẶC cuối chuỗi ($). Đảm bảo 'MySQL' ở cuối hoặc trước dấu phẩy.
4. Kết quả
+-------------------------+
| Subjects |
+-------------------------+
| SQL Server,MySQL,PL/SQL |
+-------------------------+
Cách tiếp cận thay thế (MySQL 8.0+)
Sử dụng JSON_TABLE hoặc MEMBER OF (nếu lưu dưới dạng JSON array), nhưng REGEXP phổ biến hơn cho dữ liệu cũ.
Lưu ý hiệu suất
REGEXPkhông sử dụng chỉ mục thông thường → quét toàn bảng.- Với bảng lớn, cân nhắc chuẩn hóa dữ liệu: tách thành bảng liên kết (many-to-many) hoặc dùng
FIND_IN_SET()(chỉ dùng cho danh sách đơn giản, không có dấu phẩy trong giá trị). FIND_IN_SET('MySQL', Subjects)cũng hoạt động nhưng chậm hơn REGEXP trên dữ liệu lớn.