SQL 语法错误 - ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR

SQL Syntax error - ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR

提问人:p-arth 提问时间:10/4/2023 最后编辑:mechnicovp-arth 更新时间:10/4/2023 访问量:45

问:

我创建了一个在 Rails 上构建 SQL 查询的方法,但我遇到了语法错误,不知道为什么,代码对我来说是正确的。 也许这里有人能够找到问题所在?这可能是一些很明显的事情,我没有注意到。

我的代码:

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

我得到的错误:

ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR:  syntax error at or near ")" LINE 2: AND ("title", location) IN () ^ : SELECT * FROM word_group_values WHERE account_id = 110
 AND ("title", location) IN ()
SQL Ruby Rails-ActiveRecord

评论


答:

1赞 Cattani 10/4/2023 #1

您的查询是

SELECT * FROM word_group_values WHERE account_id = 110  AND ("title", location) IN ()

由于为空,因此您将得到一个空字符串,这是一个无效的查询。info_arr

(syntax error at or near ")正在抱怨空虚())

您需要传递一个元组数组才能使其有效。在这种情况下,普通字符串可能不起作用,除非是空的。info_arr

2赞 mechnicov 10/4/2023 #2

我不知道为什么你需要SQL字符串,但要按两列过滤记录,你可以按照这个原则构建SQL查询:

SELECT * FROM table WHERE (column1, column2) IN ((valu11, value21), (valu12, value22));

这意味着您的字符串中需要外括号和内括号

不要忘记清理 SQL 查询

def build_query(account_id:, word_group_id:, titles_locations_filters: [])
  base_query =
    ActiveRecord::Base.sanitize_sql(
      [
        <<~SQL.squish,
          SELECT * FROM word_group_values
          WHERE account_id = :account_id
          AND word_group_id <> :word_group_id
        SQL
        account_id:, word_group_id:
      ]
    )

  return base_query if titles_locations_filters.empty?

  title_locations =
    titles_locations_filters.map do |title, location|
      ActiveRecord::Base.sanitize_sql([
        '(:title, :location)', # inner brackets
        title:, location:
      ])
    end.join(', ')

  "#{base_query} AND (title, location) IN (#{title_locations})" # outer brackets
end

并这样称呼它

account_id = 100
word_group_id = 200
titles_locations_filters = [%w[title1 location1], %w[title2 location2]]

build_query(account_id:, word_group_id:)
# SELECT * FROM word_group_values
# WHERE account_id = 100
# AND word_group_id <> 200

build_query(account_id:, word_group_id:, titles_locations_filters:)
# SELECT * FROM word_group_values
# WHERE account_id = 100
# AND word_group_id <> 200
# AND (title, location) IN (('title1', 'location1'), ('title2', 'location2'))