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

DA.*_*DA. 64 mysql database postgresql ruby-on-rails heroku

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

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

Mar*_*rkR 73

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

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

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

  • @MarkR当然你的建议是完美的,但OP的问题仍然有效.将查询编写为符合SQL且与平台无关的查询具有一定的价值,特别是如果将来有可能需要将系统移植到另一个数据库.显然,在这种情况下没有完美的答案. (6认同)
  • 为道德提升+1,谢谢.但是,说真的,这是正确的,比任何"只回答问题"的答案要好得多.虽然我一般都讨厌这些故事的道德答案,但在这种情况下,它做得很好. (4认同)
  • AR/AM的重点是允许您在开发和生产中使用不同的数据库后端.在我看来,这里的失败在于AR/AM如何生成查询. (3认同)
  • 我希望我不会在这里徘徊,但我对这一回应有两点反对意见.首先,这不是问题的答案.其次,在开发和生产中使用不同的数据库不是主要问题.真正错误的是抽象不用于执行不区分大小写的查询.理想情况下,活动记录将提供此功能,而无需深入到特定于供应商的SQL.我的建议是看一下http://stackoverflow.com/questions/2220423/case-insensitive-search-in-rails-model中的建议. (3认同)

Pau*_*lin 58

select * from foo where upper(bar) = upper(?);
Run Code Online (Sandbox Code Playgroud)

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

  • 你也可以确定它的上部:WHERE UPPER(bar)= UPPER(?) (11认同)
  • @Richo:但如果需要,你可以在`upper(bar)`中创建一个索引:http://www.postgresql.org/docs/current/interactive/sql-createindex.html (5认同)
  • 我不是100%肯定,但我的回忆是,这不会使用foo上可能存在的任何索引,因为它无法扫描函数对索引的返回值. (2认同)

jsw*_*ner 36

使用Arel:

Author.where(Author.arel_table[:name].matches("%foo%"))
Run Code Online (Sandbox Code Playgroud)

matches将使用ILIKEPostgres 的运算符,以及LIKE其他所有内容.

  • 希望我能给出超过+1 ......我从来不知道Arel能做到这一点!也许是因为它几乎完全没有记录?嗯... (2认同)

Ada*_*rce 13

在postgres中,你可以这样做:

SELECT whatever FROM mytable WHERE something ILIKE 'match this';
Run Code Online (Sandbox Code Playgroud)

我不确定是否有相同的MySQL,但你总是这样做有点难看,但应该在MySQL和postgres中工作:

SELECT whatever FROM mytable WHERE UPPER(something) = UPPER('match this');
Run Code Online (Sandbox Code Playgroud)


tim*_*ims 8

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

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


Ben*_*elm 5

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

    SELECT id FROM person WHERE name REGEXP 'john';
Run Code Online (Sandbox Code Playgroud)

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