【问题标题】:Pass Ruby array to SQL as values将 Ruby 数组作为值传递给 SQL
【发布时间】:2021-05-17 17:54:23
【问题描述】:
insert into table_name (attr1, attr2) VALUES 
  (1, 2),
  (3, 4)
;

我想将值插入到此表“table_name”中。但我想让它动态化。我在 ruby​​ 中有数组形式的值,如下所示:

[[1, 2], [3, 4]]

如何将 ruby​​ 数组作为值传递给 sql 查询? 我正在使用 rails 和 postgres。

【问题讨论】:

    标签: sql ruby-on-rails ruby


    【解决方案1】:

    可以使用Arel::InsertManager生成SQL插入语句:

    def insert_list(table_name:, columns:, values:)
      Arel::InsertManager.new.tap do |manager|
        table = Arel::Table.new(table_name)
        manager.into(table)
        columns.each do |name|
          manager.columns << table[name.to_sym]
        end
        manager.values = manager.create_values_list(values)
      end
    end
    
    insert_list(
       table_name: :foos, 
       columns: [:bar, :baz],
       values: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
    ).to_sql
    
    # => "INSERT INTO \"foos\" (\"bar\", \"baz\") VALUES (1, 2), (3, 4), (5, 6), (7, 8), (9, 10)"
    

    【讨论】:

    • 绝对漂亮。唯一的建议是 arel_table[name]arel_table[name.to_sym] 只是为了确保无论列最初是否是符号都有效。
    • 感谢@engineersmnky 的好建议。
    • 谢谢,但是这些行太多了,我不知道它会有多优化。我已经使用 gsub 完成了,我会发布我的答案
    • @AsbahIshaq 你为什么不尝试对它进行实际基准测试呢? Arel 的优势在于它是可移植的并且可以处理引用。我怀疑使用 gsub!在一个巨大的字符串上实际上会表现得更好。 ruby-doc.org/stdlib-2.5.3/libdoc/benchmark/rdoc/Benchmark.html
    • @max 添加一点 Bobby tables 看看这会如何影响事情:)
    【解决方案2】:

    假设你有一个模型可以使用ActiveRecord's insert_all

    Model.insert_all([{attr1: 1, attr2: 2}, {attr1: 3, attr2: 4}])
    

    【讨论】:

    • 如果您确实有模型,这将是首选方式,因为它将使用模型进行类型转换。虽然它确实有更多的开销。
    • 我没有模型,所以需要使用sql
    【解决方案3】:

    加入地图可以在这里工作:

    [[1, 2], [3, 4]].map{|inner| inner.join(", ")}
    # => ["1, 2", "3, 4"]
    [[1, 2], [3, 4]].map{|inner| inner.join(", ")}.join("),\n(")
    # => "1, 2),\n(3, 4"
    "(" + [[1, 2], [3, 4]].map{|inner| inner.join(", ")}.join("),\n(") + ")"
    # => "(1, 2),\n(3, 4)"
    puts "(" + [[1, 2], [3, 4]].map{|inner| inner.join(", ")}.join("),\n(") + ")"
    # (1, 2),
    # (3, 4)
    

    请注意,这是一个简单的解决方案。在生产应用程序中,如果数组值 [[1, 2], [3, 4]] 来自不受信任的来源(用户!),则需要清理它们以避免 SQL 注入攻击。但这似乎超出了这个问题的范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-30
      • 2016-11-23
      • 1970-01-01
      • 2016-08-01
      • 2017-10-06
      • 1970-01-01
      • 2011-03-17
      • 2018-09-26
      相关资源
      最近更新 更多