你如何写MySQL和Postgres的不区分大小写的查询?
我在本地运行MySQL数据库进行开发,但部署到使用Postgres的Heroku。 Heroku几乎处理所有事情,但是我的大小写不敏感的语句变得区分大小写。 我可以使用iLike语句,但我的本地MySQL数据库无法处理。
编写与MySQL和Postgres兼容的不区分大小写的查询的最佳方法是什么? 还是需要根据我的应用程序正在与之交谈的数据库,分别编写Like和iLike语句?
select * from foo where upper(bar) = upper(?);
如果在调用者中将参数设置为大写,则可以避免第二个函数调用。
这个故事的寓意是:不要使用不同的软件堆栈进行开发和生产。 决不。
你只会得到你不能在开发中重现的错误; 你的testing将是毫无价值的。 只是不要这样做。
使用不同的数据库引擎是没有问题的 – 将会有更多的情况下,它的行为不仅仅是LIKE(同样,你是否检查过数据库使用的sorting规则?它们在每种情况下都是一样的吗?如果没有,你可以忘记ORDER BY在varchar列工作相同)
使用Arel:
Author.where(Author.arel_table[:name].matches("%foo%"))
matches
将使用PostgreSQL的ILIKE
运算符,而LIKE
用于其他所有内容。
在postgres中,你可以这样做:
SELECT whatever FROM mytable WHERE something ILIKE 'match this';
我不确定是否有MySQL的等价物,但是你总是可以做到这一点有点丑,但应该在MySQL和Postgres的工作:
SELECT whatever FROM mytable WHERE UPPER(something) = UPPER('match this');
有几个答案,没有一个是非常令人满意的。
- LOWER(bar)= LOWER(?)可以在MySQL和Postgres上运行,但是可能会在MySQL上执行得非常糟糕 :由于LOWERfunction,MySQL不会使用它的索引。 在Postgres上,你可以添加一个函数索引(在LOWER(bar) ),但是MySQL不支持这个。
- MySQL会(除非你设置了区分大小写的sorting规则 )自动地做大小写不敏感的匹配,并使用它的索引。 ( 酒吧=? )。
- 从数据库外的代码中,维护bar和bar_lower字段,其中bar_lower包含lower(bar)的结果。 (这也可能使用数据库触发器)。 (请参阅Drupal上关于此解决scheme的讨论)。 这是笨拙的,但至less在几乎所有的数据库上都以相同的方式运行。
REGEXP不区分大小写(除非与BINARY一起使用),并且可以像这样使用…
SELECT id FROM person WHERE name REGEXP 'john';
…匹配“约翰”,“约翰”,“约翰”等
如果您使用的是PostgreSQL 8.4,则可以使用citext模块创build不区分大小写的文本字段。
你也可以考虑检查一下searchlogic插件,它为你做LIKE / ILIKE开关。
你也可以在postgres中使用〜*,如果你想匹配一个块内的子string。 〜匹配区分大小写的子string,〜*不区分大小写的子string。 这是一个缓慢的操作,但我可能会发现它对search有用。
Select * from table where column ~* 'UnEvEn TeXt'; Select * from table where column ~ 'Uneven text';
双方都会打“这里有些不一致的文字”只有前者会打“这里有些不文明的文字”
转换为upper是最好的,因为它涵盖了3个最常用的Rails数据库后端的兼容语法。 PostgreSQL,MySQL和SQLite都支持这个语法。 它有(小)缺点,你必须在你的应用程序或条件string中大写你的searchstring,使它有点丑陋,但我认为你获得的兼容性使它值得。
MySQL和SQLite3都有一个不区分大小写的LIKE运算符。 只有PostgreSQL具有区分大小写的LIKE运算符和PostgreSQL特定的(每个手册)ILIKE运算符来区分不区分大小写的search。 您可以在Rails应用程序中的条件中指定LIKE的ILIKE insead,但要注意应用程序将在MySQL或SQLite下停止工作。
第三个选项可能是检查您正在使用的数据库引擎并相应地修改searchstring。 这可能更好地通过入侵/ monkeypatching ActiveRecord的连接适配器和PostgreSQL适配器修改查询stringreplace“LIKE”“ILIKE”在查询执行之前。 然而,这个解决scheme是最复杂的,并且考虑到两个术语都更易于使用,我认为这不是什么努力(尽pipe这样做会得到很多布朗尼分)。