You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails构建SQL查询出现PG语法错误,IN子句为空求助

问题根源

看错误日志就能定位——你生成的SQL里出现了AND ("title", location) IN (),PostgreSQL不允许IN操作符后面跟空括号。这是因为当info_arr是空数组时,info_arr.join(', ')输出空字符串,直接拼进SQL就形成了非法语法。

另外还有个隐藏风险:直接把数组元素拼接进SQL,存在SQL注入漏洞,这是Rails开发里必须规避的问题。

修复方法

方法1:先判空,避免生成非法SQL

如果info_arr为空时不需要返回任何数据,可以先做判断,同时用占位符替代直接拼接:

def build_query(info_arr)
  # 空数组时返回永远不成立的条件,直接返回空结果集
  return "SELECT * FROM word_group_values WHERE 1=0" if info_arr.empty?

  <<~SQL
     SELECT * FROM word_group_values WHERE account_id = :account_id
       AND word_group_id <> :word_group_id
       AND ("title", location) IN (#{info_arr.map { |_| '(?, ?)' }.join(', ')})
  SQL
end

当info_arr有内容时,会生成(?, ?), (?, ?)这类占位符,配合Rails的参数绑定能避免注入,也不会出现空括号。

方法2:用ActiveRecord查询接口(更推荐)

别手动拼接SQL了,用Rails自带的查询方法,自动处理所有细节:

def build_query(account_id, word_group_id, info_arr)
  WordGroupValue.where(account_id: account_id)
                .where.not(word_group_id: word_group_id)
                .where("(title, location) IN (?)", info_arr)
end

Rails会自动处理info_arr为空的情况(直接返回空结果),还会自动把数组元素转成参数化的SQL片段,彻底杜绝注入风险。

注意事项

info_arr必须是二维数组,比如[["标题1", "位置1"], ["标题2", "位置2"]],这样才能匹配(title, location)的多列查询结构。

内容的提问来源于stack exchange,提问作者p-arth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:37:17