Rails代码执行带IN子句的SQL查询出现PG语法错误如何修复
错误根因
- 你从Redshift查询得到的
users数组实际是包含user_id键的哈希数组,不是纯user_id值的数组,直接join得到的字符串不符合预期。 exec_query的传参顺序错误,你把拼接后的字符串传给了第二个参数(该参数是查询名,不会参与SQL占位符替换),导致SQL中的?没有被替换,最终生成了in (?)的非法语法。
修正方案
方案1:参数绑定写法(更安全,推荐)
可以避免SQL注入风险,是Rails官方推荐的写法:
# 第一步:提取纯user_id值的一维数组 users = RedshiftRecord.connection.execute(<<~SQL select distinct user_id from tablename order by random() limit 1000 SQL ).pluck('user_id') # 第二步:动态生成和用户数量匹配的占位符 placeholders = Array.new(users.size, '?').join(',') sql = "select user_id, count(*) from tablename where user_id in (#{placeholders}) group by user_id" # 第三步:正确传参执行查询 <Library>.on_replica(:something) do Something::SomethingElse .connection .exec_query(sql, nil, users) # 第二个参数传nil,第三个参数传user_id数组做绑定 .to_h end
方案2:直接拼接SQL(仅适合user_id为整数的场景)
如果你确认user_id都是整数,不存在SQL注入风险,也可以直接拼接SQL字符串:
users = RedshiftRecord.connection.execute(<<~SQL select distinct user_id from tablename order by random() limit 1000 SQL ).pluck('user_id') sql = "select user_id, count(*) from tablename where user_id in (#{users.join(',')}) group by user_id" <Library>.on_replica(:something) do Something::SomethingElse .connection .exec_query(sql) .to_h end
内容的提问来源于stack exchange,提问作者Patthebug
相关产品推荐
相关产品推荐

