You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL ~*运算符转换为Ecto语法的正确性与等效性问询

PostgreSQL ~* 运算符转Ecto写法的等效性说明

两种写法逻辑不完全等效,核心差异如下:

  • ~*是PostgreSQL内置的不区分大小写正则匹配运算符,原SQL col1 ~* 'AAA|bbb|CcC'的匹配规则是:只要col1字段值中包含AAA/bbb/CcC任意一个子串(匹配时忽略大小写)就命中,比如aAAxxx、xxBBByy这类包含目标子串的值都能匹配成功。
  • 你当前写的Ecto代码用无通配符的ilike拼接OR条件,匹配规则是:col1字段值完全等于AAA/bbb/CcC其中一个(忽略大小写)才命中,比如只有AAA、aaa这类完全匹配的值能命中,xxAAA这类包含子串的值无法匹配,和原SQL逻辑不一致。

修正方案

方案1:保持OR拼接逻辑,对齐原SQL语义

如果要继续用ilike实现相同的子串匹配效果,需要给匹配值前后加通配符%:

from t1 in "table1",
  where: ilike(t1.col1, "%AAA%") or ilike(t1.col1, "%bbb%") or ilike(t1.col1, "%CcC%"),
  select: %{col1: t1.col1}

这种写法生成的SQL还是OR拼接形式,运行逻辑和原~*写法等价,但匹配目标字符串包含%/_等ilike特殊字符时需要额外转义。

方案2:直接调用~*运算符,和原SQL完全一致

用Ecto的fragment方法直接执行原生运算符,生成的SQL和你原始写法完全相同:

from t1 in "table1",
  where: fragment("? ~* ?", t1.col1, "AAA|bbb|CcC"),
  select: %{col1: t1.col1}

这种写法更简洁,性能也更优,但匹配目标字符串包含|/.等正则元字符时需要按正则规则转义。

补充说明

如果你的需求本身就是「不区分大小写完全匹配三个值其中一个」,那你当前的Ecto写法逻辑是正确的,只是和你给出的原SQL语义不同。


内容的提问来源于stack exchange,提问作者hnhl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 23:45:03