如何在Arel和Rails中进行LIKE查询?


115

我想做类似的事情:

SELECT * FROM USER WHERE NAME LIKE '%Smith%';

我在Arel中的尝试:

# params[:query] = 'Smith'
User.where("name like '%?%'", params[:query]).to_sql

但是,这变为:

SELECT * FROM USER WHERE NAME LIKE '%'Smith'%';

Arel正确包装了查询字符串'Smith',但是因为这是LIKE语句,所以它不起作用。

如何在Arel中进行LIKE查询?

PS奖金-我实际上是在尝试扫描表上的两个字段,包括名称和描述,以查看查询是否匹配。那将如何工作?


1
我更新了竞技场的红利答案。
2014年

Answers:


275

这是您在arel中执行类似查询的方式:

users = User.arel_table
User.where(users[:name].matches("%#{user_name}%"))

PS:

users = User.arel_table
query_string = "%#{params[query]}%"
param_matches_string =  ->(param){ 
  users[param].matches(query_string) 
} 
User.where(param_matches_string.(:name)\
                       .or(param_matches_string.(:description)))

10
与using不同where("name like ?", ...),此方法在不同数据库之间更具可移植性。例如,它将导致在ILIKE针对Postgres db的查询中使用。
dkobozev 2011年

20
这可以防止SQL注入吗?
sren 2012年

7
这不能完全防止SQL注入。尝试将user_name设置为“%”。该查询将返回匹配结果
travis-146

5
我尝试直接使用params进行sql注入User.where(users[:name].matches("%#{params[:user_name]}%")),我尝试了TRUNCATE users;此类查询,但在sql方面没有任何反应。对我来说看起来很安全。
earlonrails

5
使用.gsub(/[%_]/, '\\\\\0')转义MySQL的通配符字符。
aercolino 2013年

116

尝试

User.where("name like ?", "%#{params[:query]}%").to_sql

PS。

q = "%#{params[:query]}%"
User.where("name like ? or description like ?", q, q).to_sql

Aaand已经很长时间了,但是@ cgg5207添加了一个修改(如果您要搜索长名称或多个长名称参数,或者您懒得键入,则非常有用)

q = "%#{params[:query]}%"
User.where("name like :q or description like :q", :q => q).to_sql

要么

User.where("name like :q or description like :q", :q => "%#{params[:query]}%").to_sql

9
Rails如何知道不要%在替换字符串中转义?似乎,如果您只想要单面通配符,则没有什么可以阻止用户提交包含%两端的查询值(我知道在实践中,Rails会阻止%在查询字符串中显示,但是似乎应该在ActiveRecord级别对此加以保护)。
史蒂文

8
这难道不容易受到SQL注入攻击吗?
Behrang Saeedzadeh 2011年

7
@Behrang no 8)User.where(“ %% {{params [:query]}%之类的名称或%#{params [:query]}%之类的描述”)。)to_sql很容易受到攻击,但格式如下所示,Rails逃脱了params [:query]
Reuben Mallaby

对不起,题外话。我有方法to_sql或Arel Manager 的SQL git ,如何在db上执行sql?
МалъСкрылевъ

Model.where(to_sql_result)
Pedro Rolo

4

使用参数绑定可以进一步缩短Reuben Mallaby的答案:

User.where("name like :kw or description like :kw", :kw=>"%#{params[:query]}%").to_sql
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.