13

我在正常的正則表達式PostgreSQL和ActiveRecord的地方:正則表達式匹配

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

它匹配的

first last 
Last first 
First Last 
First name 

前三,我試圖讓所有的記錄創造了這個正則表達式,其中full_name兩勝我寫的正則表達式。我正在使用PostgreSQL

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

這是我的嘗試。我也試過SIMILAR TO~沒有運氣

回答

36

你LIKE查詢:

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

不會起作用,因爲LIKE不理解正則表達式分組((...))或交替(|),喜歡既懂_爲一個字符(如正則表達式中的.)和%,用於零個或多個字符的任何序列(例如正則表達式中的.*)。

如果您將該模式交給SIMILAR TO,那麼您會發現'first last',但由於案例問題而沒有其他人;然而,這個:

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

將照顧案件的問題,並找到相同的正則表達式。

如果你想使用正則表達式(你可能會這樣做,因爲LIKE是非常有限和繁瑣的,SIMILAR TO是一些SQL標準小組委員會的狂熱頭腦的奇怪產品),那麼你會想要使用不區分大小寫的匹配運算和你原來的正則表達式:

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

這相當於該位的AR:

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

有一個在我的代碼,你需要採取注意到了微妙的變化:我m使用單引號爲我的Ruby字符串,你使用雙引號。反斜槓在雙引號字符串中的含義比在單引號字符串中的含義多,因此'\s'"\s"是不同的東西。折騰一對夫婦to_sql電話,你可能會看到一些有趣的東西:

> 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') 

這種差別可能不會導致你任何問題,但你需要的時候每個人都希望使用相同的轉義字符要非常小心你的字符串。就個人而言,我使用單引號字符串,除非我特別需要雙引號字符串的額外轉義和字符串插值功能。

一些演示:http://sqlfiddle.com/#!15/99a2c/6

+1

這是我在這裏,由於收到的最好的答案之一。 我不需要'+'因爲我非常確定所有記錄都只有一個空格。 你使用符號':pat'的原因是爲正確的值定義正則表達式?另外,如果我需要將多個值傳入SQL,那麼創建符號將有助於跟蹤值。 – Patrick

+1

我使用':pat'而不是'?'使其更具可讀性,當只有一個佔位符時,這並不重要,但當有多個位置時需要使用相同的值時,這樣做並不重要。給事情的名字是一個可讀性贏得國際海事組織。無論如何,謝謝,我喜歡贏得積分,並且越向我學習越好:) –

+3

供參考:如果您使用的是MySQL,則不存在'〜*'運算符。相反,在其位置使用'REGEXP'。 – jerzy