2013-01-03 35 views
9

Tôi đang tìm cách truy vấn cơ sở dữ liệu tên rượu, trong đó có nhiều dấu (nhưng không theo cách thống nhất, và vì vậy các loại rượu tương tự có thể được nhập có hoặc không có dấu)Truy vấn MySQL REGEXP - tìm kiếm theo cách không nhạy cảm

các truy vấn cơ bản như sau:

SELECT * FROM `table` WHERE `wine_name` REGEXP '[[:<:]]Faugères[[:>:]]' 

mà sẽ trả lại các mục với 'Faugères' trong tiêu đề, nhưng không phải là 'Faugeres'

SELECT * FROM `table` WHERE `wine_name` REGEXP '[[:<:]]Faugeres[[:>:]]' 

làm điều ngược lại.

Tôi đã nghĩ cái gì đó như:

SELECT * 
FROM `table` 
WHERE `wine_name` REGEXP '[[:<:]]Faug[eèêéë]r[eèêéë]s[[:>:]]' 

thể làm như lừa, nhưng điều này chỉ trả về những kết quả mà không có điểm nhấn.

Trường được đối chiếu dưới dạng utf8_unicode_ci, từ trường tôi đọc là như thế nào.

Bất kỳ đề xuất nào ?!

+0

Tôi cũng gặp vấn đề tương tự. Xem chủ đề của tôi tại đây: http://stackoverflow.com/questions/33722136/how-to-search-string-using-entity-framework-with-contains-and-with-accent-insen/34047990#34047990 – Dan

Trả lời

4

You're out of luck:

Cảnh báo

Các REGEXP và RLIKE khai thác công trình theo kiểu byte-khôn ngoan, vì vậy chúng không đa byte an toàn và có thể tạo ra kết quả bất ngờ với đa byte bộ nhân vật. Ngoài ra, các toán tử này so sánh các ký tự theo giá trị byte của chúng và các ký tự có dấu có thể không được so sánh bằng ngay cả khi một đối chiếu nhất định xử lý chúng như nhau.

Các toán tử khai báo chi tiết là các điểm đánh dấu cho ranh giới từ. Gần nhất bạn có thể đạt được với các nhà điều hành LIKE là một cái gì đó trên dòng này:

SELECT * 
FROM `table` 
WHERE wine_name = 'Faugères' 
    OR wine_name LIKE 'Faugères %' 
    OR wine_name LIKE '% Faugères' 

Như bạn có thể thấy nó không phải là hoàn toàn tương đương bởi vì tôi đã hạn chế các khái niệm về ranh giới từ để không gian. Thêm nhiều mệnh đề cho các ranh giới khác sẽ là một mớ hỗn độn.

Bạn cũng có thể sử dụng tìm kiếm toàn văn (mặc dù nó không giống nhau) nhưng bạn không thể xác định chỉ mục văn bản đầy đủ trong bảng InnoDB (chưa).

Bạn chắc chắn ra khỏi may mắn :)

+0

Ouch. .. - OK, vì vậy nếu tôi chuyển sang: WHERE 'wine_name' LIKE '% Faugeres%' có nhược điểm nào không? Tôi không thể nhớ tại sao chúng tôi sử dụng REGEXP để bắt đầu, nhưng tôi nghĩ rằng đó là việc tìm kiếm toàn bộ các từ và không phải là chuỗi trong các từ, mà tuyên bố trên sẽ ... – freestate

+0

Giải pháp này có thể không tốt vì nó sẽ không hoạt động nếu từ đó có các ký tự khác sau hoặc trước nó, như: ´Faugères.´´´augères! ´ ´Faugères? ´ ´ (Faugères´ và nhiều biến thể khác. Tôi đang tìm kiếm sự lấy mẫu: REGEXP sử dụng ranh giới từ nhưng không nhạy cảm. – steps

1

utf8_general_ci thấy không có sự khác biệt giữa giọng/no giọng khi sắp xếp. Có thể điều này cũng đúng cho các tìm kiếm. Ngoài ra, thay đổi REGEXP thành LIKE. REGEXP so sánh nhị phân.

0

Ok tôi vừa vấp vào câu hỏi này trong khi tìm kiếm thứ gì đó khác.

Điều này trả về đúng sự thật.

SELECT 'Faugères' REGEXP 'Faug[eèêéë]+r[eèêéë]+s'; 

Hy vọng điều đó sẽ hữu ích.

Thêm '+' Cho biết regexp tìm kiếm một hoặc nhiều lần xuất hiện của các ký tự.

0

Để giải quyết vấn đề này, tôi đã thử những thứ khác nhau, bao gồm sử dụng từ khóa nhị phân hoặc bộ ký tự latin1 nhưng không có kết quả.
Cuối cùng, xem xét rằng nó là một lỗi MySql, tôi đã kết thúc thay thế E và E chars,

Như thế này:

SELECT * 
FROM `table` 
WHERE replace(replace(wine_name, 'é', 'e'), 'è', 'e') REGEXP '[[:<:]]Faugeres[[:>:]]' 
3

Vì REGEXP và RLIKE được byte định hướng, bạn đã thử:

SELECT 'Faugères' REGEXP 'Faug(e|è|ê|é|ë)r(e|è|ê|é|ë)s'; 

Điều này cho biết một trong số này phải có trong biểu thức. Lưu ý rằng tôi đã không sử dụng dấu cộng (+) bởi vì điều đó có nghĩa là MỘT HOẶC THÊM. Vì bạn chỉ muốn một bạn không nên sử dụng dấu cộng.

0

Tôi đã gặp sự cố tương tự khi tìm mọi bản ghi phù hợp với một trong các mẫu sau: 'copropriété', 'copropriete', 'COPROPRIÉTÉ', 'Copropri? T?'

REGEXP 'copropri.{1,2}t.{1,2} đã làm việc cho tôi. Về cơ bản, .{1,2} sẽ hoạt động trong mọi trường hợp khi nhân vật được mã hóa 1 hoặc 2 byte.

Giải thích: https://dev.mysql.com/doc/refman/5.7/en/regexp.html

Cảnh báo
Các REGEXP và khai thác RLIKE làm việc theo kiểu byte-khôn ngoan, vì vậy họ không multibyte an toàn và có thể tạo ra kết quả bất ngờ với bộ ký tự nhiều byte. Ngoài ra, các toán tử này so sánh các ký tự theo giá trị byte của chúng và các ký tự có dấu có thể không được so sánh bằng nhau ngay cả khi một đối chiếu nhất định xử lý chúng như nhau.

Các vấn đề liên quan