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

如何使用Knex在MsSQL中通过单次查询更新多行数据?

兄弟,我太懂你翻遍SO找不到合适方案的憋屈了!你要的批量更新多条不同实体的位置参数完全可以实现,分原生SQL和Knex.js两种场景给你捋清楚:

原生SQL实现(分主流数据库)

不同数据库的批量更新语法略有差异,这里给你最常用的两种写法:

MySQL 写法

兼容所有MySQL版本的CASE WHEN方案

这种写法最通用,不管版本高低都能跑:

UPDATE entities
SET 
  x = CASE id
    WHEN 1 THEN 2
    WHEN 2 THEN 5
    WHEN 3 THEN 10
    WHEN 4 THEN 20
  END,
  y = CASE id
    WHEN 1 THEN 2
    WHEN 2 THEN 5
    WHEN 3 THEN 10
    WHEN 4 THEN 20
  END,
  o = CASE id
    WHEN 1 THEN 90
    WHEN 2 THEN 0
    WHEN 3 THEN 270
    WHEN 4 THEN 180
  END
WHERE id IN (1, 2, 3, 4);

MySQL 8.0+ 更简洁的JOIN方案

如果你的MySQL版本是8.0及以上,可以用VALUES行构造器结合JOIN,写法更直观:

UPDATE entities e
JOIN (
  VALUES 
    (1, 2, 2, 90),
    (2, 5, 5, 0),
    (3, 10, 10, 270),
    (4, 20, 20, 180)
) AS temp(id, x, y, o) ON e.id = temp.id
SET e.x = temp.x, e.y = temp.y, e.o = temp.o;

PostgreSQL 写法

PostgreSQL支持直接用FROM子句关联临时数据集更新,语法很清晰:

UPDATE entities e
SET x = temp.x, y = temp.y, o = temp.o
FROM (
  VALUES 
    (1, 2, 2, 90),
    (2, 5, 5, 0),
    (3, 10, 10, 270),
    (4, 20, 20, 180)
) AS temp(id, x, y, o)
WHERE e.id = temp.id;
Knex.js 实现

Knex本身没有原生的批量更新语法,但可以通过两种方式实现需求:

动态生成CASE WHEN语句

这种方式兼容所有数据库,和原生SQL的CASE WHEN思路一致:

const updatedEntities = [
  {id:1, x:2, y:2, o:90}, 
  {id:2, x:5, y:5, o:0}, 
  {id:3, x:10, y:10, o:270}, 
  {id:4, x:20, y:20, o:180}
];

// 封装一个生成CASE WHEN的工具函数
const buildCaseClause = (column) => {
  let caseStmt = knex.raw(`CASE id`);
  updatedEntities.forEach(entity => {
    caseStmt = caseStmt.when(entity.id, entity[column]);
  });
  return caseStmt.end();
};

// 执行批量更新
await knex('entities')
  .update({
    x: buildCaseClause('x'),
    y: buildCaseClause('y'),
    o: buildCaseClause('o')
  })
  .whereIn('id', updatedEntities.map(item => item.id));

用Knex.raw结合行构造器(适合高版本MySQL/PostgreSQL)

如果你的数据库支持行构造器,可以直接用knex.raw拼接原生SQL的简洁写法:

// MySQL 8.0+ 版本
await knex.raw(`
  UPDATE entities e
  JOIN (VALUES ?) AS temp(id, x, y, o) ON e.id = temp.id
  SET e.x = temp.x, e.y = temp.y, e.o = temp.o
`, [updatedEntities.map(item => [item.id, item.x, item.y, item.o])]);

// PostgreSQL 版本
await knex.raw(`
  UPDATE entities e
  SET x = temp.x, y = temp.y, o = temp.o
  FROM (VALUES ?) AS temp(id, x, y, o)
  WHERE e.id = temp.id
`, [updatedEntities.map(item => [item.id, item.x, item.y, item.o])]);

额外提醒

不管用哪种方式,都建议把批量更新放在事务里执行,避免部分更新失败导致数据不一致。比如Knex里可以用knex.transaction包裹更新逻辑。

内容的提问来源于stack exchange,提问作者Barrard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 09:13:15