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

如何用supabase-js执行Upsert并返回全部目标记录?

解决Supabase upsert后返回所有目标记录的问题

当前使用upsert+ignoreDuplicates: true+select的方式只能返回新增插入的行,要实现无论记录新增还是已存在都返回所有目标记录,可以采用以下两种简洁方案:

方案一:利用伪更新返回冲突行

PostgreSQL的ON CONFLICT DO NOTHING不会返回冲突的已存在记录,但DO UPDATE会返回被操作的行。我们可以设置一个无实际修改的更新操作,既不改变原有数据,又能让Supabase返回冲突的记录:

const values = await supabase.from(user_reftext)
  .upsert(dataArray, {
    onConflict: 'col_a, col_b',
    // 设置无实际意义的更新,触发返回冲突行
    update: { col_a: supabase.raw('col_a') }
  })
  .select()

注意事项:

  • 该操作会触发表上的UPDATE触发器(如果存在),若业务依赖更新逻辑,需评估影响。
  • 可替换为任意表中存在的字段,比如col_b: supabase.raw('col_b'),核心是不修改原有数据。

方案二:分两步查询+插入,合并结果

如果不想触发UPDATE相关逻辑,可拆分操作:先查询已存在的记录,再插入不存在的记录,最后合并两组结果:

// 提取所有要操作的联合键组合
const keyPairs = dataArray.map(item => ({ col_a: item.col_a, col_b: item.col_b }));

// 第一步:查询已存在的记录
const { data: existingRecords, error: queryErr } = await supabase
  .from(user_reftext)
  .select()
  .or(keyPairs.map(pair => `col_a.eq.${pair.col_a},col_b.eq.${pair.col_b}`).join(','));

if (queryErr) {
  throw queryErr;
}

// 第二步:过滤出不存在的记录并插入
const newRecordsToInsert = dataArray.filter(item => {
  return !existingRecords.some(record => 
    record.col_a === item.col_a && record.col_b === item.col_b
  );
});

const { data: insertedRecords, error: insertErr } = await supabase
  .from(user_reftext)
  .upsert(newRecordsToInsert, {
    onConflict: 'col_a, col_b',
    ignoreDuplicates: true
  })
  .select();

if (insertErr) {
  throw insertErr;
}

// 合并得到所有目标记录
const allTargetRecords = [...existingRecords, ...insertedRecords];

优势:

  • 不会触发UPDATE操作,避免不必要的触发器执行。
  • 逻辑直观,易于理解和维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 03:15:57