【问题标题】:Update different columns on multiple rows in a single query在单个查询中更新多行的不同列
【发布时间】:2017-10-08 13:19:52
【问题描述】:

假设我们有下表:

id | col_a | col_b | col_c
1  |   abc |  null |  qwqw
2  |  null |  null |  null
3  |  null |  ijij |  cba

我们想要进行以下更新:

  • 第 1 行:SET col_a = cba
  • 第 2 行:SET col_b = uiui, col_c = zxzx
  • 第 3 行:SET col_b = null

首先,是否可以在一个查询中完成?

如果没有,最好的选择是什么?

  • 每行一个查询,例如 UPDATE table SET ... WHERE id=1;
  • 获取行,用新值替换旧值,然后执行大量 INSERT INTO table VALUES ... ON CONFLICT (id) DO UPDATE SET col_a = EXCLUDED.col_a, col_b = EXCLUDED.col_b, col_c = EXCLUDED .col_c;
  • 还有别的吗?

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    最简单的方法是三个updates

    update t
        set col_a = cba
        where id = 1;
    
    update t
        set col_b = uiui, col_c = zxzx
        where id = 2;
    
    update t
        set col_b = null
        where id = 3;
    

    您可以将它们包装在一个事务中,以便它们同时生效。假设您在id 上有一个索引,这应该有很好的性能。

    您可以使用条件逻辑将它们放入单个语句中:

    update t
        set col_a = (case when id = 1 then cba else col_a end),
            col_b = (case when id = 2 then uiui 
                          when id = 3 then null
                          else col_b
                     end),
            col_c = (case when id = 2 then zxzx else col_c end)
        where id in (1, 2, 3);
    

    我认为三个单独的语句更清晰,更不容易出错。

    【讨论】:

    • 感谢您的单一声明。这就是我一直在寻找的。您认为它在其他 3 个单独的查询中具有任何性能优势吗?在这里,为了简单起见,我只提出了 3 次更新的问题,但在实际情况下,我会有更多更新,而且非常频繁,因此我正在寻找任何可能的性能改进。
    • @leyou 。 . .如果where 条件使用索引,则单个事务中的单独更新应该提供合理的性能。 on conflict 方法很聪明,应该也可以工作。如果您要更新表中很大比例的行,那么截断并重新插入可能是最快的方法。
    • 我通过模拟 10,000 个随机行更新在我的笔记本电脑上进行了一些快速测试。每行更新使用一个查询大约需要 12 秒。使用“select + insert on conflict”大约需要 6 秒。而使用单个语句,大约需要 5 秒。
    • @leyou 。 . .当您每行执行一个查询时,您是使用单个事务进行三个更新还是每次更新使用一个单独的事务?
    • 我的错,我没有。再次使用单个事务进行三个更新,现在“每次更新一个查询”大约需要 8 秒。这是我用来做测试的代码:pastebin.com/XGjjQRhH
    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 2014-10-29
    • 1970-01-01
    相关资源
    最近更新 更多