3

我正在尝试使用 activerecord-import 导入数据,但遇到了问题。如果该行已经存在,则需要对其进行更新,否则需要创建该行。表中的唯一行由两列的组合定义,其中每个列的值在表中可能不是唯一的。由于列不是唯一列,我将如何使用 on_duplicate_key_update 的冲突目标。

现在了解详情。我有一个名为 Order 的模型,下面是 Order 模型中列的简化版本。

id
order_number
sku_number
quantity

数据库中的唯一行由 order_number 和 sku_number 的组合标识。id 列是自动递增的。通常,如果我有一个唯一列作为标识符,我可以执行以下操作。因此,在下面的示例中,假设 id 列是唯一标识符,我将使用 id 列作为冲突目标。

order = Order.create(order_number: '1', sku_number: '1', quantity: 100)
order.quantity = 200
Order.import [order], on_duplicate_key_update: {conflict_target: [:id], columns: [:quantity]}

这将更新数量,因为订单已经存在。

但我需要的是类似

Order.import [order], on_duplicate_key_update: {conflict_target: [:order_number, :sku_number], columns: [:quantity]}

order_number 和 sku_number 将唯一标识冲突行。

但这失败了,因为 Postgres 期望冲突目标的唯一列。

有没有办法使用非唯一列(即 order_number 和 sku_number)调用 on_duplicate_key_update?

任何帮助将不胜感激。

4

2 回答 2

4

我想到了。我正在放下解决方案,以防其他人遇到同样的问题。

我最终在 Order 上创建了一个唯一索引

class AddUniqueKeyConstraintToOrders < ActiveRecord::Migration
  def change
    add_index :orders, [:order_number, :sku_number], unique: true
  end
end

activerecord-import 支持使用索引作为约束。所以我最终做了类似的事情

order = Order.last
order.quantity = 200
Order.import [order], on_duplicate_key_update: {conflict_target: [:order_number, :sku_number], index_name: :index_orders_on_order_number_and_sku_number, columns: [:quantity]}

其中 index_orders_on_order_number_and_sku_number 是迁移创建的索引的名称。它将数量从以前的值更新为 200,而没有创建额外的记录。

于 2016-10-12T12:13:52.333 回答
0

另一种方法是创建一个 CONSTRAIANT 作为多列的唯一组合。在 create_table 之后的迁移文件中,我们可以:

create_table :board_statistics do |t|
    t.string :hostname, null: false
    t.string :slot
    …

end

只创建一个唯一索引

add_index :board_statistics, [:hostname, :slot, :serial_number], unique: true

或创建约束

execute <<-SQL                                                                                                        
       ALTER TABLE board_statistics  
        ADD CONSTRAINT one_card_xan_slot UNIQUE (hostname, slot, serial_number);
 SQL

约束可以在 Activerecord-import gem 中使用,例如:

BoardStatistic.import columns, on_duplicate_key_ignore: {constraint_name: :one_card_xan_slot}
于 2017-12-13T13:49:51.303 回答