在 Rails 查询中转义引号

Posted

技术标签:

【中文标题】在 Rails 查询中转义引号【英文标题】:Escaping Quotes in Rails Query 【发布时间】:2020-07-17 08:38:42 【问题描述】:

我有包含以下字段的商家表

Merchant(id: integer, name: string, logo: string, description: text, categories: string, created_at: datetime, updated_at: datetime)

我想使用 name 属性运行 first_or_create 查询。问题是名称列包含单引号,例如 Brandy's Boy。

mname = "brandy's boy"
conds = "lower(name) = #mname"

Merchant.where(conds)

Merchant Load (1.5ms)  SELECT  "merchants".* FROM "merchants" WHERE "merchants"."deleted_at" IS NULL AND (lower(name) = 'brandy's boy ') LIMIT $1  [["LIMIT", 11]]

输出:

#<Merchant::ActiveRecord_Relation:0x000055d0f72a2ce0>

但是当我运行静态查询时,这会给我输出。

Merchant.where("lower(name) = ?", 'Brandy\'s Boy'.downcase)

Merchant Load (3.7ms)  SELECT  "merchants".* FROM "merchants" WHERE "merchants"."deleted_at" IS NULL AND (lower(name) = 'brandy''s boy') LIMIT $1  [["LIMIT", 11]]

#<ActiveRecord::Relation [#<Merchant id: 1413, name: "Brandy's Boy", logo: nil, description: "ABC", categories: [], created_at: "2020-07-17 07:32:29", updated_at: "2020-07-17 07:32:29">]>

但是变量 mname 是在循环中填充的,它是动态的。所以在这种情况下,我需要转义单引号并获得所需的结果(现有 Brandy's Boy Merchant 对象)

请帮忙。

【问题讨论】:

【参考方案1】:

您不需要插值来为where 创建参数,只需绑定它/它们:

Merchant.where("lower(name) = ?", mname)

Active Record 会处理这个问题,您的查询很可能如下所示:

SELECT "merchants".* FROM "merchants" WHERE (lower(name) = 'brandy''s boy')

转义是在框架的内部进行的,来自文档:

如果传递一个数组,则处理数组的第一个元素 作为模板,其余元素插入到 模板来生成条件。 Active Record 负责 构建查询以避免注入攻击,并将从 ruby 类型到需要的数据库类型。元素被插入 按它们出现的顺序放入字符串中。

User.where(["name = ? and email = ?", "Joe", "joe@example.com"])
# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';

在做:

Merchant.where(["lower(name) = ?", mname])

和做的差不多一样

Merchant.where("lower(name) = ?", mname)

因此您的查询按上述方式处理。

【讨论】:

以上是关于在 Rails 查询中转义引号的主要内容,如果未能解决你的问题,请参考以下文章

NamedParameterJdbcTemplate Oracle SQL,如何在命名查询中转义单引号?

在数据库查询字符串中转义引号的好方法?

在 JavaScript 中转义字符串

在速度模板中转义引号

如何在 Presto 中转义单引号?

如何在 MySQL 中转义单引号