【问题标题】:Regex working in regex engine but not in postgresql正则表达式在正则表达式引擎中工作,但不在 postgresql 中
【发布时间】:2015-05-14 10:56:44
【问题描述】:

我尝试在管道分隔的字符串中匹配数字 13,如下所示:

13 - match
1|2|13 - match
13|1|2 - match
1|13|2 - match

1345|1|2 - should fail
1|1345|2 - should fail
1|2|1345 - should fail
1|4513|2 - should fail
4513|1|2 - should fail
2|3|4|4513- should fail

所以,如果13 只出现在开头或结尾,或者在字符串之间作为一个整体,它应该匹配。

为此,我编写了以下正则表达式:

^13$|(\|13\|)?(?(1)|(^13\||\|13$))

Regex101 中,它按预期工作。请点击链接查看我的示例。


但在 Postgresql 中,它会为以下查询引发错误:

SELECT * FROM tbl_privilage WHERE user_id = 24 and show_id ~ '^13$|(\|13\|)?(?(1)|(^13\||\|13$))';

错误:

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

SQL 状态:2201B

【问题讨论】:

  • "管道分隔字符串",你为什么要这样存储你的数据?这会产生大量问题,您的正则表达式只是众多问题之一。尝试修复真正的问题,即您的数据模型,而不是为了修复错误而修复错误。
  • @FrankHeikens 我已经问过为什么我们不遵循规范化但他们强迫我通过正则表达式检查它我们不应该像人们回答我的那样改变架构设计而且我也没有权利:(
  • 如果您不/不能规范化,请至少使用一个 ARRAY。仍然是一种解决方法,但比一个问题要好得多。
  • @FrankHeikens 感谢您的建议,因为我没有对生产环境的数据库访问权限,我已经建议高级官员使用任何集合对象,如您所说的数组,但他们说我们已经开发了很多 php 代码取决于这个管道分隔值,所以没有办法改变它。您只是尝试使用模式匹配来完成此任务,因此我使用正则表达式进行了尝试。但我喜欢使用 a_horse_with_no_name 答案。再次感谢您的反馈。

标签: regex postgresql


【解决方案1】:

不要使用正则表达式,使用数组更健壮(也可能更高效):

select *
from the_table
where '13' = any (string_to_array(the_column, '|'));

这假定值和分隔符之间没有空格。您甚至可以索引该表达式,这可能会加快搜索速度。

但我同意弗兰克的观点:你应该真的修复你的数据模型。

【讨论】:

  • 你说得对,“但我同意弗兰克的观点”,但我没有生产环境的访问权限,但我会再次坚持我的上级官员,谢谢。
【解决方案2】:

Documentation 很清楚,说运算符~ 实现了POSIX 正则表达式。在 Regex101 中,您使用的是 PCRE(Perl 兼容)正则表达式。两人很different

如果您在 PostgreSQL 中需要 PCRE 正则表达式,您可以设置一个扩展。喜欢pgpcre

【讨论】:

    【解决方案3】:

    您需要在单词边界内匹配13

    你需要

    [[:<:]]13[[:>:]]
    

    即使数值周围有空格,此解决方案也应该有效。

    documentation:

    括号表达式有两种特殊情况:中括号 表达式[[:&lt;:]][[:&gt;:]] 是约束,匹配空 分别位于单词的开头和结尾的字符串。

    【讨论】:

    • @stibizhev 所有正则表达式模式都像我预期的那样正常工作我通过将正则表达式分开检查它如下^13$(\|13\|)?(^13\||\|13$) 并检查但实际问题是正则表达式如果(?(1)|(^13\||\|13$))因为? 没有像我预期的那样工作。
    • 您是否在该站点上选择了 PCRE/PHP 选项?如果是,(?(1) 是一个条件表达式。 See the explanation on that siteIF Clause (?(1)|(^13\||\|13$))。您不能将 regex101 中的正则表达式直接粘贴到 PostGre 查询中,您需要确保它们与这种特殊的正则表达式风格兼容。您需要的是单词边界检查。在大多数正则表达式引擎中,它是\b。但不在 PostgreSQL 中。
    • 即使字符串中有杂散空格(例如1 | 13 | 2),正则表达式解决方案也可以工作
    • 是的,但实际上该字符串是使用 php implode 准备的,并且对于使用 yii findall AR 方法获取的传递主键,因此在我们的项目中不会发生此问题,但通常肯定会发生。而且我使用了a_horse_with_no_name的答案,我也赞成你的答案,因为指出空格可能会破坏正则表达式。我是 postgres 的新手,主要是我使用 mysql。两者都仅遵循 sql 标准,但无法实现我的预期解决方案,完全缺乏我对 postgres 函数的了解。
    猜你喜欢
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 2020-03-24
    • 2020-07-08
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多