【问题标题】:Run UPDATE query by a custom order按自定义顺序运行 UPDATE 查询
【发布时间】:2018-05-08 21:22:09
【问题描述】:

有没有办法按特定的自定义顺序更新表中的所有记录?我特别指的是一种情况,即实际订单来自“外部”(例如作为 POST 值)。

例如,有一张桌子

   id | title | order_idx
   ----------------------
    1 | lorem | 1
    2 | ipsum | 2
    3 | dolor | 3

我有一个提交隐藏字段的表单,按以下顺序携带 ID 值:2、3、1 我想更新表以在下一行中为 order_idx 添加增量编号,按照表单字段提供的 ID 顺序进行。所以在这种情况下,最终结果应该是这样的:

   id | title | order_idx
   ----------------------
    1 | lorem | 3
    2 | ipsum | 1
    3 | dolor | 2

这可以在单个 UPDATE 查询中以某种方式完成,而不是在 php 循环中运行 3 个查询(每个都包括 WHERE 子句)

【问题讨论】:

    标签: mysql sql-update increment


    【解决方案1】:

    您可以在赋值语句中使用条件表达式,如下所示:

    UPDATE t 
    SET x = CASE 
    WHEN 2 THEN 1 
    WHEN 3 THEN 2 
    WHEN 1 THEN 3
    ELSE x
    WHERE ....
    

    参数化:

    UPDATE t 
    SET x = CASE 
    WHEN ? THEN 1 
    WHEN ? THEN 2 
    WHEN ? THEN 3
    ELSE x
    WHERE ....
    

    在任何一种情况下,查询很可能需要动态构建以说明要订购的不同数量的商品。


    由于您的评论表明可能有数百... MySQL 对查询长度有限制(reference)

    如果数量较多,我会开始推荐不同的方法。

    Step 1) CREATE TEMPORARY TABLE `newOrder` (id INT, new_order_idx INT);
    Step 2) INSERT id's and their new order into the temp table.
    Step 3) UPDATE t INNER JOIN newOrder AS n ON t.id = n.id SET t.order_idx = n.new_order_idx WHERE ...
    Step 4) DROP TEMPORARY TABLE newOrder;
    

    流程本身不再是单个查询;但更新是。


    注意:如果您有一个涉及order_idx 的唯一密钥,我完全确定其中任何一个都可以工作。在我需要保持唯一性的情况下,通常的解决方案是一步将要调整的记录移到完全不同的范围,然后再移到它们的新位置。 (UPDATE t SET order_idx = -1 * order_idx WHERE ... 之类的内容将在此答案的第二部分中作为第 3 步前的范围转移。)

    【讨论】:

    • 感谢您的提示。是的,我对动态构建查询没有任何问题。我会说这比在循环中运行单个查询更好。示例是 3 行,但实际上可能有数百行
    【解决方案2】:

    使用 ON DUPLICATE KEY UPDATE,如下所示:

    INSERT INTO table (id, order_idx) VALUES (1,3),(2,1),(3,2)
    ON DUPLICATE KEY UPDATE order_idx=VALUES(order_idx);
    

    因此您可以为每一行动态设置 order_idx

    INSERT INTO table (id, order_idx) 
    VALUES (1,order_list[0]),(2,order_list[1]),(3,order_list[2])
    ON DUPLICATE KEY UPDATE order_idx=VALUES(order_idx);
    

    【讨论】:

      猜你喜欢
      • 2020-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      • 2013-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多