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

fil*_*lsa 111 activerecord ruby-on-rails arel

我想做的事情如下:

SELECT * FROM USER WHERE NAME LIKE '%Smith%';
Run Code Online (Sandbox Code Playgroud)

我在Arel的尝试:

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

但是,这变为:

SELECT * FROM USER WHERE NAME LIKE '%'Smith'%';
Run Code Online (Sandbox Code Playgroud)

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

如何在Arel中进行LIKE查询?

PS奖金 - 我其实是想扫描桌子上两个字段,这两个名称和说明,看是否有查询的任意匹配.那会怎么样?

Ped*_*olo 272

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

users = User.arel_table
User.where(users[:name].matches("%#{user_name}%"))
Run Code Online (Sandbox Code Playgroud)

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)))
Run Code Online (Sandbox Code Playgroud)

  • 这是否可以防止SQL注入? (20认同)
  • 与使用`where("name like?",...)`不同,这种方法在不同的数据库中更具可移植性.例如,它会导致在对Postgres数据库的查询中使用`ILIKE`. (10认同)
  • 这不能完全防止SQL注入.尝试将user_name设置为"%".查询将返回匹配项 (7认同)
  • 我尝试直接使用params sql注入,`User.where(users [:name] .matches("%#{params [:user_name]}%"))`,我试过`TRUNCATE users;`和其他这样的查询和在sql方面什么也没发生.看起来对我很安全. (5认同)
  • 使用```.gsub(/ [%_] /,'\\\\\ 0')```来转义MySql通配符字符. (5认同)
  • 此外,如果你不知道你可以通过`User.where(用户[:name] .matches("%TRUNCATE用户;%"))来尝试从控制台.to_sql`这将显示它被转义并包含在单引号中. (4认同)
  • Arel和`LIKE?`都可以防止任意SQL注入,但不能防止通配符注入:https://github.com/rails/arel/blob/6cf061ed6f3f9c8128385765c07eaa4f8a43bd34/test/visitors/test_to_sql.rb#L299-L302`matches(“#如果用户称自己为“%`”,则{user.name}%“)`有风险;matches(“#{sanitize_sql_like(user.name)}%”)是安全的。 (2认同)

Reu*_*aby 115

尝试

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

PS.

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

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

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

要么

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

  • Rails如何知道不会在替换字符串中转义`%`?好像你只想要一个单向通配符,没有什么可以阻止用户提交两端都包含`%`的查询值(我知道在实践中,Rails会阻止`%`出现在查询字符串中,但似乎应该在ActiveRecord级别对此进行保护). (9认同)
  • 这不容易受到SQL注入攻击吗? (8认同)
  • @Behrang no 8)User.where("名称如%#{params [:query]}%或描述,如%#{params [:query]}%").to_sql将是易受攻击的,但是,以我显示的格式,Rails逃避params [:查询] (7认同)
  • @Behrang见http://stackoverflow.com/questions/2962263/rails-sql-injection (5认同)