13

Tôi tạo ra regex này trong bình thường RegexPostgreSQL và ActiveRecord nơi: Regex phù hợp với

/(first|last)\s(last|first)/i 

Nó phù hợp với ba đầu tiên của

first last 
Last first 
First Last 
First name 

Tôi cố gắng để có được tất cả các hồ sơ nơi full_name trận đấu với regex tôi đã viết. Tôi đang sử dụng PostgreSQL

Person.where("full_name ILIKE ?", "%(first|last)%(last|first)%") 

Đây là nỗ lực của tôi. Tôi cũng đã cố gắng SIMILAR TO~ không có may mắn

Trả lời

36

truy vấn LIKE của bạn:

full_name ilike '%(first|last)%(last|first)%' 

sẽ không làm việc vì LIKE không hiểu nhóm regex ((...)) hoặc thay đổi luân phiên (|), LIKE chỉ hiểu _ cho một ký tự đơn (như . trong regex) và % cho bất kỳ chuỗi nào có số không hoặc nhiều ký tự (như .* trong regex).

Nếu bạn giao mẫu đó cho SIMILAR TO thì bạn sẽ tìm thấy 'first last' nhưng không có loại nào khác do các sự cố về chữ hoa; tuy nhiên, điều này:

lower(full_name) similar to '%(first|last)%(last|first)%' 

sẽ xử lý các vấn đề về trường hợp và tìm những vấn đề tương tự như regex của bạn.

Nếu bạn muốn sử dụng regex (bạn có thể làm vì LIKE rất hạn chế và phức tạp và SIMILAR TO, tốt, một sản phẩm lạ của tâm trí sốt của một số tiểu chuẩn tiêu chuẩn SQL) thì bạn sẽ muốn sử dụng các case-insensitive điều hành phù hợp và regex ban đầu của bạn:

full_name ~* '(first|last)\s+(last|first)' 

đó dịch để bit này của AR:

Person.where('full_name ~* :pat', :pat => '(first|last)\s+(last|first)') 
# or this 
Person.where('full_name ~* ?', '(first|last)\s+(last|first)') 

có một sự thay đổi tinh tế trong mã của tôi mà bạn cần phải lưu ý: tôi m sử dụng dấu nháy đơn cho chuỗi Ruby của tôi, bạn đang sử dụng gấp đôi báo giá. Dấu gạch chéo ngược có nghĩa là nhiều hơn trong các chuỗi được trích dẫn kép so với các chuỗi được trích dẫn một lần, vì vậy, '\s'"\s" là những thứ khác nhau. Quăng trong một vài to_sql cuộc gọi và bạn có thể thấy một cái gì đó thú vị:

> puts Person.where('full_name ~* :pat', :pat => 'a\s+b').to_sql 
SELECT "people".* FROM "people" WHERE (full_name ~* 'a\s+b') 

> puts Person.where('full_name ~* :pat', :pat => "a\s+b").to_sql 
SELECT "people".* FROM "people" WHERE (full_name ~* 'a +b') 

khác biệt đó có thể không gây ra cho bạn bất kỳ vấn đề nhưng bạn cần phải rất cẩn thận với chuỗi của bạn khi tất cả mọi người muốn sử dụng các ký tự thoát cùng. Cá nhân, tôi sử dụng các chuỗi được trích dẫn đơn trừ khi tôi đặc biệt cần thêm tính năng thoát và chức năng nội suy chuỗi của chuỗi được trích dẫn kép.

Một số bản trình diễn: http://sqlfiddle.com/#!15/99a2c/6

+1

Đây là một trong những câu trả lời hay nhất tôi đã nhận được ở đây, Cảm ơn. Tôi không cần '+' vì tôi khá chắc chắn rằng tất cả các bản ghi chỉ có một không gian duy nhất. Lý do tại sao bạn sử dụng biểu tượng ': pat' là định nghĩa regex làm giá trị sau đúng không? Ngoài ra, nếu tôi cần chuyển nhiều giá trị vào SQL, thì việc tạo các biểu tượng sẽ giúp theo dõi các giá trị. – Patrick

+1

Tôi sử dụng ': pat' thay vì'?'để làm cho nó dễ đọc hơn một chút, điều này không quan trọng nhiều khi chỉ có một trình giữ chỗ, nhưng nó có khi có nhiều hơn hoặc nếu bạn cần sử dụng cùng một giá trị ở một vài nơi. Đặt tên cho mọi thứ là một IMO có thể đọc được. Dù sao, cảm ơn, tôi muốn kiếm được điểm của tôi và càng có nhiều bạn học hỏi từ tôi càng tốt :) –

+3

FYI: nếu bạn đang sử dụng MySQL, toán tử '~ *' không tồn tại. Thay vào đó, hãy sử dụng 'REGEXP' ở vị trí của nó. – jerzy

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