2009-03-18 5 views
62

Tôi muốn viết một truy vấn SQL tìm kiếm từ khóa trong trường văn bản, nhưng chỉ khi đó là "toàn bộ từ khớp" (ví dụ: khi tôi tìm kiếm "thoát" , nó không phải phù hợp với "khô cằn", nhưng nó phải phù hợp với "một thoát khỏi".Tìm kiếm "toàn bộ từ khớp" trong MySQL

tôi đang sử dụng MySQL.

may mắn thay, hiệu suất là không quan trọng trong ứng dụng này, và kích thước cơ sở dữ liệu và kích thước chuỗi đều thoải mái nhỏ, nhưng tôi muốn làm điều đó trong SQL hơn trong PHP lái nó.

Trả lời

129

Bạn có thể sử dụng REGEXP[[:<:]][[:>:]] dấu word-ranh giới:

SELECT * 
FROM table 
WHERE keywords REGEXP '[[:<:]]rid[[:>:]]' 
+2

Chỉ cần lưu ý, các chuỗi sử dụng các ký tự đặc biệt biểu thức chính quy phải được thoát. –

+1

Nhưng một vấn đề khác cho việc thiết lập ranh giới từ là nó có thể coi các giai đoạn là ranh giới từ, vì vậy nếu bạn có ý định khớp tên, thì nó có thể không hoạt động như mong đợi. chọn 'R.C. Sproul 'regexp' R \ .C \. ';/* Trả về 1 */... chọn 'R.C. Sproul 'regexp' [[: <:]] R \ .C \. [[:>:]] '/ * Trả về 0 */ –

+0

@ LukeH - Cảm ơn người đàn ông. Điều này thật tuyệt. và tôi đã sử dụng RLIKE là có bất kỳ sự khác biệt giữa trong cả hai REGEX vs RLIKE. –

2
select blah blah blah 
where column like 'rid %' 
    or column like '% rid' 
    or column like '% rid %' 
    or column = 'rid' 
+0

Tùy thuộc vào tình huống, bạn cũng nên cẩn thận với dấu chấm câu. Ví dụ, không ai trong số đó sẽ trả về 'thoát'. –

+3

Tôi nghĩ rằng truy vấn là không đủ. Điều gì về một số văn bản như "thoát", hoặc "(thoát)"? – wenqiang

1
select * from table where Locate('rid ', FieldToSearch) > 0 
     or Locate(' rid', FieldToSearch) > 0 

Điều này sẽ xử lý việc tìm ra nơi nó được đi trước hoặc theo sau là một khoảng trắng, bạn có thể mở rộng cách tiếp cận để tính đến.,?! và như vậy, không thanh lịch nhưng dễ dàng.

1

Đây là câu trả lời tốt nhất mà tôi đã đưa ra bản thân mình với cho đến nay:

SELECT * FROM table 
WHERE keywords REGEXP '^rid[ $]' OR keywords REGEXP ' rid[ $]' 

tôi sẽ đã đơn giản hóa nó để:

SELECT * 
FROM table 
WHERE keywords REGEXP '[^ ]rid[ $]' 

nhưng [^] có một ý nghĩa đặc biệt của " KHÔNG phải là một không gian ", thay vì" dòng đầu hoặc không gian ".

REGEXP so sánh với nhiều điều kiện LIKE như thế nào? (Không phải là vấn đề hiệu suất trong ứng dụng này.)

+2

Nếu bạn đã làm nó [^], tôi nghĩ rằng thứ hai sẽ làm việc.^chỉ là "không" khi nó là ký tự đầu tiên trong một tập hợp, IIRC. –

+0

Tôi tự hỏi nếu SQL REGEXP có một trường "ranh giới từ" như Perl \ b? Điều đó sẽ xử lý dấu cách, dấu chấm câu, v.v. –

+0

@Andy, MySql sử dụng [[: <:]] and [[:>:]] làm điểm đánh dấu đường biên. – LukeH

23

Tìm thấy một câu trả lời để ngăn chặn từ ranh giới cổ điển [[::<::]] đụng độ với ký tự đặc biệt ví dụ như . @ # $%^* &

Thay thế ..

SELECT * 
FROM table 
WHERE keywords REGEXP '[[:<:]]rid[[:>:]]' 

Với điều này ..

SELECT * 
FROM table 
WHERE keywords REGEXP '([[:blank:][:punct:]]|^)rid([[:blank:][:punct:]]|$)' 

Kết quả sau (không gian, tab, vv) || (dấu phẩy, khung, v.v.) || bắt đầu/kết thúc của dòng. Một kết quả ranh giới từ 'hoàn thành' hơn.

+0

Mã này không hoạt động đối với tôi. Tôi nhận được: 'Lỗi: Bạn có lỗi trong cú pháp SQL của mình; kiểm tra hướng dẫn tương ứng với phiên bản máy chủ MySQL của bạn cho đúng cú pháp để sử dụng gần '' ([[[: blank:] [: punct:]] 'tại dòng 3 SQLState: 42000 ErrorCode: 1064' Bất kỳ ide? – Solver42

+0

@ Solver42 Tôi vừa thử lại truy vấn trên với mysql 5.6.21 và nó hoạt động như bình thường. Hãy thử loại bỏ khung đầu tiên khỏi ''([[[' ​​ –

+0

Tôi đã thử nhưng có cùng Lỗi. [[: trống:]] | [[: dấu chấm câu:]] | ^) thoát ([[: dấu chấm câu:]} | [[: trống:]] | $) – Solver42

1

Sử dụng regexp với ranh giới từ, nhưng nếu bạn muốn tìm kiếm không nhạy cảm, hãy lưu ý rằng REGEXP là toán tử một byte, vì vậy không có gì đáng để có đối chiếu utf8_general_ci, khớp sẽ không có dấu trọng âm.

Để có cả chữ không nhạy cảm và toàn bộ từ phù hợp, hãy chỉ định từ được viết theo cùng cách với hàm PHP (không được chấp nhận) sql_regcase() đã làm.

Trong thực tế:

  • utf8_general_ci cho phép bạn thực hiện một sự bình đẳng (WHERE lĩnh vực = giá trị) trường hợp và giọng tìm kiếm không nhạy cảm nhưng nó không cho phép bạn chỉ định toàn bộ một trận đấu từ (ranh giới từ cột mốc không công nhận)

  • NHƯ phép bạn trường hợp và giọng tìm kiếm không nhạy cảm nhưng bạn phải tự xác định tất cả các kết hợp của khả năng từ ranh giới charactes (đánh dấu ranh giới từ không được công nhận)

  • ranh giới từ [[: <:]] và [[:>:]] được hỗ trợ trong REGEXP, là một hàm byte đơn, do đó, không thực hiện tìm kiếm không nhạy cảm.

Giải pháp là sử dụng REGEXP có ranh giới từ và từ được sửa đổi theo cách sql_regcase.

Được sử dụng trên http://www.genovaperte.it