是否可以强制 Sequel 始终返回带有重复密钥更新的 autoincrement id?

Can Sequel be forced to always return autoincrement id with ON DUPLICATE KEY UPDATE?

我正在使用 Sequel (4.x) 和 MySQL 5.5,在一个主要执行 INSERT 且偶尔执行的重写应用程序上更新现有行。 Sequel 在 .insert() 操作后返回一个 AUTO_INCREMENT id。

我目前在这样的表达式中使用 .on_duplicate_key_update()

# Insert new row into cache_table, updating any columns that change
# on a key violation
id = DB[:table_name].on_duplicate_key_update.insert(
  col1: @col1,
  col2: @col2,
  created: nil,
  updated: nil
)

这会在新插入行或列的值更改时将自动increment id(LAST_INSERT_ID())返回到变量id,但如果返回0没有列的值被修改。

阅读 MySQL 文档,我明白为什么了。当执行 MySQL INSERT...ON DUPLICATE KEY UPDATE 时,MySQL 无法可靠地返回已存在但未被 UPDATE 更改的行的 AUTO_INCREMENT id。文档建议使用 UPDATE 表达式,例如:

ON DUPLICATE KEY UPDATE `id` = LAST_INSERT_ID(`id`)

我真的很想在这个特定的应用程序中避免额外的 SELECT。我如何强制 Sequel 使用相同的行为,并始终返回行 id 即使没有任何实际更改?

使用 Sequel.function() method

可以导致 Sequel 在 RDBMS 上执行一个函数

要执行 MySQL 的原生 LAST_INSERT_ID() 并将列 id 作为参数传递,请将列名称作为符号作为第二个参数传递:

Sequel.function(:last_insert_id, :id)

Dataset#on_duplicate_key_update method 接受列的散列和更新的新值,因此 :last_insert_id 函数可以传递到那里,连同要更新的其他列的显式列表:

id = DB[:table_name].on_duplicate_key_update(
  # Call the native LAST_INSERT_ID()
  id: Sequel.function(:last_insert_id, :id),
  col1: @col1,
  col2: @col2,
  updated: nil
).insert(
  col1: @col1,
  col2: @col2,
  created: nil,
  updated: nil
)

此方法可靠地 returns 将 LAST_INSERT_ID() 转换为 id,而无需执行 SELECT 查询。

注意: INSERT...ON DUPLICATE KEY UPDATE 导致table的AUTO_INCREMENT值前进如果 table 包含除 AUTO_INCREMENT 主键之外的任何其他 UNIQUE 索引,则更新行时。这不是 Sequel 特有的,只是使用 ON DUPLICATE KEY UPDATE.

时的一般警告

如果这不是 acceptable,您可能需要求助于单独的 SELECT 而不是在 DB.insert() returns [=27= 时检索 ID ].