Postgres正则表达式问题

时间:2012-08-22 09:02:40

标签: regex postgresql

我需要找到存储在postgres中的所有记录,这些记录匹配以下regexp:

^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}$

这样的事情:

SELECT * FROM users WHERE users.phone ~ '^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}$'

但是这个错误:

  

无效的正则表达式:量词操作数无效

为什么Postgres不会使用这个正则表达式?

在普通Ruby中使用相同的工作正常。

更新

问题仅出在WHERE。当我尝试:

SELECT '+79637434199' ~ '^((8|\+7)[\- ]?)(\(?\d{3}\)?[\- ]?)[\d\- ]{7,10}'

Postgres返回true。但是当我尝试时:

SELECT * FROM users WHERE users.phone ~ '^((8|\+7)[\- ]?)(\(?\d{3}\)?[\- ]?)[\d\- ]{7,10}'

结果:“正则表达式无效:量词操作数无效”

1 个答案:

答案 0 :(得分:4)

当你把它放在第一个或最后一个位置时,你不需要在字符类中转义-,因为它不能被误读为范围:

[\- ] - > [- ]
[\d\- ] - > [\d -]

你拥有它的方式最后的10是徒劳的 最后添加$以禁止尾随字符 或\D禁止尾随数字(但需要非数字) 或者($|\D)要么在那里结束字符串,要么有非数字跟随。

放在一起:

SELECT '+79637434199' ~ '^(8|\+7)[ -]?(\(?\d{3}\)?[ -]?)[\d -]{7,10}($|\D)'

否则你的表达式很好,它适用于PostgreSQL 9.1.4。无论你是在WHERE子句还是SELECT列表中使用它都不应该有任何区别 - 除非你遇到一些旧版本的bug(比如评论中建议的@kgrittn)。


如果我在E前面加上字符串文字,我可以激发你得到的错误信息。此无法解释您的问题,因为您声明该表达式可以正常工作SELECT

但是,正如夏洛克·福尔摩斯所引用的那样,“当你排除了不可能的事物时,无论剩下什么,无论多么不可能,都必须是真理。”

也许您使用standard_conforming_strings = on运行了一个测试而另一个使用standard_conforming_strings = off运行 - 这是9.1之前的旧版本中字符串文字的默认解释。也许有两个不同的客户(对此有不同的设置)。

请阅读手册中的String Constants with C-style Escapes一章。