如何通过正则表达式从mysql数据库中选择记录

时间:2012-11-23 13:17:50

标签: mysql ruby-on-rails ruby regex scope

我有一个regexp来验证用户电子邮件地址。

/^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})$/i"

在活动记录的帮助下,我想从数据库中获取其电子邮件地址与此正则表达不匹配的所有用户。我尝试了以下scope来获得所需的结果,但我得到的只是ActiveRecord::Relation

scope :not_match_email_regex, :conditions => ["NOT email REGEXP ?'", /^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})$/"]

这给了我以下查询:

SELECT `users`.* FROM `users` WHERE (email REGEXP '--- !ruby/regexp /^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\\-+)|([A-Za-z0-9]+\\.+)|([A-Za-z0-9]+\\++))*[A-Za-z0-9]+@((\\w+\\-+)|(\\w+\\.))*\\w{1,63}\\.[a-zA-Z]{2,})$/\n...\n')

我还尝试使用相同的结果以下列方式定义此scope

scope :not_match_email_regex, :conditions => ["email REGEXP '(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})'"]

它生成的查询是:

SELECT `users`.* FROM `users` WHERE (email REGEXP '(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+.+)|([A-Za-z0-9]+++))*[A-Za-z0-9]+@((w+-+)|(w+.))*w{1,63}.[a-zA-Z]{2,})')

如何获取与给定正则表达式匹配或不匹配的所有记录?

2 个答案:

答案 0 :(得分:2)

编辑12-11-30 小修正部分根据@innocent_rifle的评论

此处建议的Regexp尝试进行与原始问题相同的匹配

1。在我第一次编写它的解决方案中,我忘了你必须在字符串中转义\因为我在MySQL中直接测试。在讨论Regexps时,在字符串中使用Regexps会让人感到困惑,因此我将使用此表单,例如/dot\./.source(在Ruby中)将提供"dot\\."

2. REGEXP in MySQL(手册5.6,在5.0.67中测试过)使用“字符串中的C转义语法”,因此WHERE email REGEXP '\.'仍然与{ {1}},要找到必须使用WHERE email REGEXP '.'的字符".",要实现这一点,您必须使用代码WHERE email REGEXP '\\.'。使用.where([ 'email REGEXP ?', "\\\\."])(MySQL需要2次转义)更具可读性。但是,我更喜欢使用.where([ 'email REGEXP ?', /\\./.source ]),然后我不必担心你需要多少逃脱。

3。您不需要在正则表达式中转义.where([ 'email REGEXP ?', /[.]/.source ]),而不是在"-"中使用它时,只要该字符是第一个或最后一个


我发现了一些错误:它是第一个正则表达式 - 或“|”在你的表达式中,它应该是查询中的String,或者使用我喜欢的Regexp#source。我认为最后还有一个额外的引用。 除此之外你真的确定正则表达式有效。如果你在控制台上尝试使用字符串?

另请注意,您不会在db中捕获带NULL的电子邮件,在这种情况下,您必须添加[]

我的MySQL版本中的Regexp语法。

我还测试了@Olaf Dietsche在他的建议中所写的内容,似乎不需要它,但强烈建议强烈建议遵循标准语法(<your existing expr in parentheses>) OR IS NULL或{{1} })。

我做了一些检查,必须更改这些内容:使用NOT (expr REGEXP pat)代替expr NOT REGEXP pat,而[A-Za-z0-9_]无效,您必须使用\w({{ 1}}如果是字符串),使用\+(在Regexp或字符串中)更容易。

它导致在MySQL中 REGEXP

\\+

小变更建议

我完全不理解你的正则表达式,所以这只是改变你的正则表达式而不改变它会发现的东西。

首先:如上所述更改整个字符串

然后改变

"\\\\+"

[+]

'^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]+)|([A-Za-z0-9]+[+]+))*[A-Za-z0-9]+@(([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]))*[A-Za-z0-9]{1,63}[.][a-zA-Z]{2,}$'

(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]+)|([A-Za-z0-9]+[+]+))*

最终代码(如果您愿意,请更改为([A-Za-z0-9]+[-+_.]+)* 语法)。 我试图通过 @innocent_rifle找到与评论相同的字符串,只在@(([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]))* 右侧的表达式中添加@([A-Za-z]+[-.]+)*

..., :conditions => ...

答案 1 :(得分:0)

要验证电子邮件地址,您可能需要考虑How to Find or Validate an Email Address。至少,这个regexp看起来有点简单。

根据MySQL - Regular Expressions,正确的语法是

expr REGEXP pat

匹配,

expr NOT REGEXP patNOT (expr REGEXP pat)

反之。不要忘记第二版中的大括号。