我对使用问号之间的差异感到困惑,例如
Foo.find(:all, :conditions => ['bar IN (?)', @dangerous])
并使用sprintf样式字段类型,例如
Bar.find(:all, :conditions => ['qux IN (%s)', @dangerous])
消毒投入。是否有任何安全优势,如果你知道你正在寻找一个数字 - 比如一个ID - 而不是一个字符串,在使用%d over?,或者你只是在字符串出现时要求一个大的讨厌错误?
在Rails 3和4中使用较新的.where语法是否会发生这种变化?
答案 0 :(得分:1)
%s
适用于字符串。主要区别在于%s
不添加引号。来自ActiveRecord::QueryMethods.where
:
最后,您可以在模板中使用sprintf样式的%escapes。这个 与以前的方法略有不同;你是 负责确保模板中的值正确 引。这些值将传递给连接器以进行引用,但是 来电者有责任确保将它们括在引号中 结果SQL。引用后,使用相同的值插入值 作为Ruby核心方法
Kernel::sprintf
逃脱。
<强>示例:强>
User.where(["name = ? and email = ?", "Joe", "joe@example.com"])
# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
User.where(["name = '%s' and email = '%s'", "Joe", "joe@example.com"])
# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
更新
您正在传递数组。 %s
似乎在参数上调用.to_s
,因此这可能无法按预期工作:
User.where("name IN (%s)", ["foo", "bar"])
# SELECT * FROM users WHERE (name IN ([\"foo\", \"bar\"]))
User.where("name IN (?)", ["foo", "bar"])
# SELECT * FROM users WHERE (name IN ('foo','bar'))
对于简单查询,您可以使用散列表示法:
User.where(name: ["foo", "bar"])
# SELECT * FROM users WHERE name IN ('foo', 'bar')
答案 1 :(得分:1)
据我所知,%s
只是在您的查询中插入了@dangerous.to_s
恰好是什么,并且您对此负责。
例如,如果@dangerous是一个整数数组,那么你将得到一个SQL错误:
@dangerous = [1,2,3]
User.where("id IN (%s)", @dangerous)
将导致以下错误语法:
SELECT `users`.* FROM `users` WHERE (id IN ([1, 2, 3]))
,而:
User.where("id IN (?)", @dangerous)
生成正确的查询:
SELECT `users`.* FROM `users` WHERE (id IN (1,2,3))
因此,在我看来,除非你非常非常清楚你正在做什么,否则你应该让?
运算符完成它的工作,特别是如果你不相信@dangerous
的内容安全。