Regex – biểu thức chính quy trong MySQL

Regex là viết tắt của Regular Expression (biểu thức chính quy), một phương pháp linh hoạt và mạnh mẽ để so sánh chuỗi sử dụng các khuôn mẫu (được gọi là pattern, hơi khó hiểu nhưng lát nữa đọc hết bạn sẽ hình dung được). Bài viết được xây dựng dựa theo MySQL Document, chạy trên MySQL 8.0.26.

Thông thường, khi ta muốn lấy dữ liệu từ MySQL chúng ta thường sử dụng lệnh SELECT với điều kiện nào đó. Ví dụ:

SELECT * FROM student_table WHERE name = 'Hoang Thuy Linh';

Tuy nhiên nếu muốn tăng độ khó lên 1 chút như tìm tất cả những người tên Linh thì ta sử dụng LIKE

SELECT * FROM student_table WHERE name LIKE '%Linh%';

Tuy nhiên muốn tìm những người tên Linh mà địa chỉ nhà không có số nhà thì làm thế nào. Lúc này câu lệnh REGEX rất hữu dụng.

SELECT * FROM student_table 
WHERE name LIKE '%Linh%' AND address NOT REGEXP '[0-9]';

Trong đó address là từ khóa để so sánh, ‘[0-9]’ là pattern đặc tả dữ liệu mà ta mong muốn so sánh.

Quảng cáo

Ủng hộ website

Một số hàm biểu thức chính quy

chuỗi REGEXP pattern : So sánh chuỗi và pattern sau đó trả về kết quả 1 nếu khớp, ngược lại trả về 0

chuỗi NOT REGEXP pattern : Ngược lại với REGEXP

REGEXP_LIKE(chuỗi, pattern [,kiểu tùy chọn]) : Hàm này trả về kết quả là 1 nếu chuỗi khớp với pattern, nếu không trả về 0. Nếu chuỗi hoặc pattern là NULL nó sẽ trả về NULL

REGEXP_INSTR(chuỗi, pattern[, vị trí bắt đầu tìm kiếm, tần suất xuất hiện, giá trị trả về, kiểu tùy chọn]) : Hàm này trả về vị trí bắt đầu của chuỗi con trong chuỗi lớn khớp với pattern.

Cú pháp của các pattern

^: Khớp với phần bắt đầu 1 chuỗi

SELECT 'Linh' REGEXP '^Linh';         -- kết quả 1
SELECT 'Hello Linh' REGEXP '^Linh';    -- kết quả 0

$: Khớp với phần kết thúc 1 chuỗi

SELECT 'Linh hello' REGEXP 'Linh$';    -- kết quả 0
SELECT 'Hello Linh' REGEXP 'Linh$';    -- kết quả 1

. Dấu chấm này sẽ đại diện cho ký tự đơn bất kỳ

SELECT 'Linh hello' REGEXP 'Linh.';     -- kết quả 1, vì phía sau Linh có ký tự dấu cách
SELECT 'Hello Linh' REGEXP 'Linh.';     -- kết quả 0, vì phía sau Linh không còn ký tự nào

a*: Dấu hoa thị * thể hiện ký tự “a” xuất hiện từ 0 đến nhiều lần (chỉ duy nhất ký tự “a” thôi nhé)

SELECT 'Hello Linh nn' REGEXP 'Lin*h';   -- kết quả 1
SELECT 'Hello Lih' REGEXP 'Lin*h';       -- kết quả 1
SELECT 'Hello Linnnnh' REGEXP 'Lin*h';   -- kết quả 1

a+: Dấu + thể hiện chữ “a” xuất hiện từ 1 đến nhiều lần (chỉ duy nhất chữ “a” thôi nhé)

SELECT 'Hello Linh' REGEXP 'Lin+h';          -- kết quả 1
SELECT 'Hello Lih' REGEXP 'Lin+h';           -- kết quả 0

a?: Dấu ? thể hiện ký tự “a” xuất hiện 1 lần hoặc không xuất hiện

SELECT 'Hello Lnh' REGEXP 'Li?nh';      -- kết quả 1
SELECT 'Hello Linh' REGEXP 'Li?nh';     -- kết quả 1
SELECT 'Hello Liinh' REGEXP 'Li?nh';    -- kết quả 0

de|abc: Dấu | ở giữa thể hiện cho việc khớp chuỗi “de” hoặc chuỗi “abc”

SELECT 'Hello Linh' REGEXP 'Linh|Huong';    -- kết quả 1
SELECT 'Hello Duyen' REGEXP 'Linh|Huong';   -- kết quả 0
SELECT 'Hello Huong' REGEXP 'Linh|Huong';   -- kết quả 1
SELECT 'Huong' REGEXP '^(Linh|Huong)$';     -- kết quả 1
SELECT 'Linh' REGEXP '^(Linh|Huong)$';      -- kết quả 1
SELECT 'Huongx' REGEXP '^(Linh|Huong)$';    -- kết quả 0

(abc)* : thể hiện chuỗi “abc” xuất hiện từ 0 đến nhiều lần

SELECT 'Linh' REGEXP '^(Linh)*$';         -- kết quả 1
SELECT 'HelloLinh' REGEXP '^(Linh)*$';    -- kết quả 0
SELECT 'LinhLinh' REGEXP '^(Linh)*$';     -- kết quả 1

(abc){n} hoặc (abc){n,m} thể hiện sự xuất hiện của chuỗi “abc” xuất hiện chính xác n lần hoặc từ n đến m lần (n bắt buộc phải nhỏ hơn hoặc bằng m). Nếu theo như cách thể hiện này thì:

  • a* có thể viết là a{0,}
  • a+ có thể viết là a{1,}
  • a? có thể viết là a{0,1}
SELECT 'Linh' REGEXP '(Linh){2}';              -- kết quả 0
SELECT 'Hello LinhLinh' REGEXP '(Linh){2}';    -- kết quả 1
SELECT 'Hello Linh Linh' REGEXP '(Linh){2}';   -- kết quả 0

Giải thích về pattern (Linh){2} tức là chuỗi “Linh” xuất hiện 2 lần liền kề nhau, do đó chuỗi “Hello Linh Linh” không hợp lệ do có dấu cách. Điều này các bạn cần lưu ý vì nhiều bạn hiểu rằng chữ “Linh” cứ xuất hiện 2 lần là sai nhé

[a-dX] hoặc [^a-dX] thể hiện sự xuất hiện của một trong bất kỳ ký tự nào trong cặp dấu ngoặc vuông a hoặc b hoặc c hoặc d hoặc X, nếu có dấu ^ thì ngược lại

SELECT 'aYbc' REGEXP '[a-dXYZ]';       -- Kết quả 1
SELECT 'aYbc' REGEXP '^[a-dXYZ]$';     -- Kết quả 0
SELECT 'aYbc' REGEXP '^[a-dXYZ]+$';    -- Kết quả 1
SELECT 'aYbc' REGEXP '^[^a-dXYZ]+$';   -- Kết quả 0
SELECT 'Linh' REGEXP '^[^a-dXYZ]+$';   -- Kết quả 1
SELECT 'Linha' REGEXP '^[^a-dXYZ]+$';  -- Kết quả 0
SELECT 'ab56' REGEXP '^[a-d1-9]+$';    -- Kết quả 1

[:character_class:] MySQL cung cấp 1 số class để khớp pattern với chuỗi ví dụ class số, class chữ, class ký tự đặc biệt. Các tên class cơ bản mình viết ở bên dưới nhé

SELECT 'abc56' REGEXP '^[[:alnum:]]+$';    -- Kết quả 1
SELECT 'abc56' REGEXP '^[[:alpha:]]+$';    -- Kết quả 0
SELECT '    ' REGEXP '^[[:blank:]]+$';     -- Kết quả 1
alnumCác ký tự chữ và số
alphaCác ký tự chữ
blankCác ký tự khoảng trắng
cntrlCác ký tự điều khiển
digitCác ký tự số
graphCác ký tự đồ họa
lowerCác ký tự chữ thường
printCác ký tự đồ họa và khoảng trắng
punctCác ký tự chấm câu
spaceCác ký tự khoảng trắng, tab (\t), xuống dòng (\n) hoặc Carriage Return (\r)
upperCác ký tự chữ hoa
xdigitCác ký tự là chữ số thập lục phân (Hexadecimal digit)

\ : Dấu \ được sử dụng trước các ký tự đặc biệt để khớp pattern với chuỗi

SELECT '1+2' REGEXP '1+2';     -- Kết quả 0
SELECT '1+2' REGEXP '1\+2';    -- Kết quả 0
SELECT '1+2' REGEXP '1\\+2';   -- Kết quả 1

Một số ví dụ về các pattern của REGEX

^[aeiou].* : Tìm tên của người dùng bắt đầu bằng nguyên âm

^0[^0][0-9]{8}$: Kiểm tra số điện thoại có 10 chữ số nhập vào là hợp lệ thỏa mãn các điều kiện sau: chữ số 0 ở đầu, chữ số tiếp theo khác 0, chỉ cho phép nhập 10 chữ số

^([0-9]+[a-zA-Z]+|[a-zA-Z]+[0-9]+)[0-9a-zA-Z]*$: Kiểm tra biển số xe nhập vào theo điều kiện chuỗi nhập vào bao gồm cả chữ và số

Add Comment