133

我正在尝试像这样进行类似的查询

def self.search(search, page = 1 )
  paginate :per_page => 5, :page => page,
    :conditions => ["name LIKE '%?%' OR postal_code like '%?%'", search, search],   order => 'name'
end

但是当它运行时,添加引号会导致 sql 语句像这样出现

SELECT COUNT(*)
FROM "schools" 
WHERE (name LIKE '%'havard'%' OR postal_code like '%'havard'%')):

所以你可以看到我的问题。我正在使用我从未使用过的 Rails 4 和 Postgres 9,所以不确定它是一个 activerecord 的东西还是可能是一个 postgres 的东西。

我该如何设置它,以便我'%my_search%'在最后的查询中喜欢?

4

7 回答 7

243

您的占位符被一个字符串替换,您没有正确处理它。

代替

"name LIKE '%?%' OR postal_code LIKE '%?%'", search, search

"name LIKE ? OR postal_code LIKE ?", "%#{search}%", "%#{search}%"
于 2013-09-30T23:57:17.843 回答
52

不要使用conditionsRails 2 的语法,而是使用 Rails 4 的where方法:

def self.search(search, page = 1 )
  wildcard_search = "%#{search}%"

  where("name ILIKE :search OR postal_code LIKE :search", search: wildcard_search)
    .page(page)
    .per_page(5)
end

注意:上面使用参数语法而不是?占位符:这些都应该生成相同的 sql。

def self.search(search, page = 1 )
  wildcard_search = "%#{search}%"

  where("name ILIKE ? OR postal_code LIKE ?", wildcard_search, wildcard_search)
    .page(page)
    .per_page(5)
end

注意:使用ILIKE名称 - LIKE 的 postgres 不区分大小写版本

于 2013-10-01T00:07:59.607 回答
25

虽然字符串插值会起作用,但由于您的问题指定了 rails 4,您可以为此使用 Arel 并保持您的应用程序数据库不可知。

def self.search(query, page=1)
  query = "%#{query}%"
  name_match = arel_table[:name].matches(query)
  postal_match = arel_table[:postal_code].matches(query)
  where(name_match.or(postal_match)).page(page).per_page(5)
end
于 2013-12-15T01:59:18.673 回答
9

ActiveRecord 足够聪明,知道 引用的参数?是一个字符串,因此它用单引号将其括起来。正如一篇文章所建议的那样,您可以使用 Ruby 字符串插值来用所需的%符号填充字符串。但是,这可能会使您面临 SQL 注入(这很糟糕)。我建议您使用 SQLCONCAT()函数来准备字符串,如下所示:

"name LIKE CONCAT('%',?,'%') OR postal_code LIKE CONCAT('%',?,'%')", search, search)

于 2017-03-28T12:50:27.413 回答
5

尝试

 def self.search(search, page = 1 )
    paginate :per_page => 5, :page => page,
      :conditions => ["name LIKE  ? OR postal_code like ?", "%#{search}%","%#{search}%"],   order => 'name'
  end

有关更多信息,请参阅有关 AREL 条件的文档。

于 2013-09-30T23:57:49.400 回答
3

如果有人使用"key"or之类的列名"value",那么您仍然会看到与您的 mysql 查询语法错误相同的错误。这应该解决:

.where("`key` LIKE ?", "%#{key}%")
于 2020-08-31T07:11:53.963 回答
-1
.find(:all, where: "value LIKE product_%", params: { limit: 20, page: 1 })
于 2016-12-28T08:14:07.750 回答