我正在尝试在rails中运行以下原始查询,只是为了看到它失败:
query = 'SELECT * FROM users WHERE id IN ($1);'
results = ActiveRecord::Base.connection.exec_query(query, "My query", [ [1,2] ]);
我做错了什么?
我得到的错误始于:
Could not log "sql.active_record" event. NoMethodError: undefined method `binary?' for 1:Fixnum
显然,我在某种程度上误用[1, 2]
绑定参数,但我自己找不到合适的例子。
P.S。这是最小的失败示例,派生自更高级的查询,无法转换为ActiveRecord调用链。换句话说 - 在构建查询时我不能依赖Arel。
P.P.S。我正在使用rails 4.0.1
和postgresql 9.3
答案 0 :(得分:13)
我很确定你的NoMethodError来自日志记录。如果我们看exec_query
,我们会看到:
def exec_query(sql, name = 'SQL', binds = [])
log(sql, name, binds) do
# call exec_no_cache(sql, binds) or exec_cache(sql, binds)...
然后,如果我们查看exec_cache
,我们会看到:
def exec_cache(sql, binds)
#..
@connection.send_query_prepared(stmt_key, binds.map { |col, val|
type_cast(val, col)
})
所以binds
应该是列/值对。 PostgreSQL驱动程序期望col
成为列对象,以便它可以询问它的名称是什么以及它应该如何格式化val
,log
调用exec_query
使用该信息。 {1}}在Rails日志中生成一些漂亮且易读的东西。一些实验表明,您可以使用nil
作为col
,一切都很愉快。
这意味着我们已经转向了这个:
exec_query(
'SELECT * FROM users WHERE id IN ($1)',
'my query',
[ [nil, [1,2]] ]
)
底层驱动程序可能知道或不知道如何处理[1,2]
数组,我只有可以测试PostgreSQL扩展的Rails3,它不喜欢[1,2]
。如果Rails4也不喜欢该数组,那么你可以逐个传递参数:
exec_query(
'SELECT * FROM users WHERE id IN ($1, $2)',
'my query',
[ [nil,1], [nil,2] ]
)
答案 1 :(得分:2)
我最近遇到了类似的问题。事实证明,在where in (?)
中,ActiveRecord期待一个字符串,而不是一个数组。所以你可以尝试传入一串逗号分隔的ID,这应该可以解决问题。