你如何为MySQL和Postgres编写不区分大小写的查询?

时间:2008-10-15 01:10:29

标签: mysql ruby-on-rails database postgresql heroku

我在本地运行MySQL数据库进行开发,但部署到使用Postgres的Heroku。 Heroku几乎可以处理所有事情,但是我的不区分大小写的Like语句变得区分大小写。我可以使用iLike语句,但我的本地MySQL数据库无法处理。

编写与MySQL和Postgres兼容的不区分大小写的查询的最佳方法是什么?或者我是否需要根据我的应用正在与之交谈的数据库编写单独的Like和iLike语句?

11 个答案:

答案 0 :(得分:73)

这个故事的寓意是:不要使用不同的软件堆栈进行开发和生产。从不。

你最终会得到你无法在开发中重现的错误;你的测试将毫无价值。只是不要这样做。

使用不同的数据库引擎是不可能的 - 会有更多的情况,它的行为与LIKE不同(同样,您是否检查了数据库使用的排序规则?在每种情况下它们是否相同?如果不是,你可以忘记在varchar列上工作的ORDER BY)

答案 1 :(得分:58)

select * from foo where upper(bar) = upper(?);

如果在调用者中将参数设置为大写,则可以避免第二次函数调用。

答案 2 :(得分:36)

使用Arel:

Author.where(Author.arel_table[:name].matches("%foo%"))

matchesILIKE运算符用于Postgres,LIKE用于其他所有运算符。

答案 3 :(得分:13)

在postgres中,你可以这样做:

SELECT whatever FROM mytable WHERE something ILIKE 'match this';

我不确定是否有相同的MySQL,但你总是这样做有点难看,但应该适用于MySQL和postgres:

SELECT whatever FROM mytable WHERE UPPER(something) = UPPER('match this');

答案 4 :(得分:8)

有几个答案,其中没有一个非常令人满意。

  • LOWER(bar)= LOWER(?)将在MySQL和Postgres上工作,但很可能在MySQL上执行:MySQL由于LOWER功能,不会使用其索引。在Postgres上你可以添加一个功能索引(在 LOWER(bar)),但是MySQL不支持这个。
  • MySQL将(除非您设置区分大小写的collation)自动进行不区分大小写的匹配,并使用其索引。 ( bar =?)。
  • 从数据库外的代码中,维护 bar bar_lower 字段,其中bar_lower包含 lower(bar)的结果。 (这也许可以使用数据库触发器)。 (参见Drupal)对此解决方案的讨论。这很笨拙,但至少在每个数据库上都运行相同的方式。

答案 5 :(得分:5)

REGEXP不区分大小写(除非与BINARY一起使用),并且可以像这样使用...

    SELECT id FROM person WHERE name REGEXP 'john';

...匹配'John','JOHN','john'等等。

答案 6 :(得分:2)

如果您正在使用PostgreSQL 8.4,则可以使用citext模块创建不区分大小写的文本字段。

答案 7 :(得分:2)

答案 8 :(得分:1)

您也可以考虑查看searchlogic插件,该插件会为您执行LIKE/ILIKE切换。

答案 9 :(得分:1)

如果要匹配块中的子字符串,也可以在postgres中使用〜*。 〜匹配区分大小写的子字符串,〜*不区分大小写的子字符串。它运行缓慢,但我觉得它对搜索很有用。

Select * from table where column ~* 'UnEvEn TeXt';
Select * from table where column ~ 'Uneven text';

两者都会出现“这里有些不均匀的文字” 只有前者才会出现“这里有一些不合时宜的文字”

答案 10 :(得分:0)

转换为upper是最好的,因为它涵盖了3个最常用的Rails数据库后端的兼容语法。 PostgreSQL,MySQL和SQLite都支持这种语法。它有(次要的)缺点,你必须在你的应用程序或条件字符串中大写你的搜索字符串,使它有点丑,但我认为你获得的兼容性使它值得。

MySQL和SQLite3都有一个不区分大小写的LIKE运算符。只有PostgreSQL具有区分大小写的LIKE运算符和PostgreSQL特定的(根据手册)ILIKE运算符,用于不区分大小写的搜索。您可以在Rails应用程序的条件中指定LIKE的ILIKE insead,但请注意该应用程序将在MySQL或SQLite下停止工作。

第三个选项可能是检查您正在使用的数据库引擎并相应地修改搜索字符串。这可能更好地通过入侵/ monkeypatching ActiveRecord的连接适配器并让PostgreSQL适配器修改查询字符串以在查询执行之前用“LIKE”代替“ILIKE”。然而,这个解决方案是最复杂的,并且考虑到更容易的方式,如上限这两个术语,我认为这不是努力(尽管你这样做会获得大量的布朗尼点)。