[求助]关于批量更新数据的时候,指定更新顺序的问题

UPDATE accounts
SET balance = CASE
    WHEN account_number = '50012014' THEN 0
    WHEN account_number = '40210042' THEN 0
    WHEN account_number = '1010000228' THEN 0
    WHEN account_number = '1010006973' THEN 0
    WHEN account_number = '719770' THEN 0
    WHEN account_number = '719772' THEN 0
    WHEN account_number = '719781' THEN 0
    WHEN account_number = '719790' THEN 0
    ELSE balance
END,
credit = CASE
    WHEN account_number = '50012014' THEN 90
    WHEN account_number = '40210042' THEN 0
    WHEN account_number = '1010000228' THEN 0
    WHEN account_number = '1010006973' THEN 0
    WHEN account_number = '719770' THEN 0
    WHEN account_number = '719772' THEN 0
    WHEN account_number = '719781' THEN 0
    WHEN account_number = '719790' THEN 0
    ELSE credit
END,
update_date = CASE
    WHEN account_number = '50012014' THEN '2024-05-16 06:37:00'
    WHEN account_number = '40210042' THEN '2024-05-16 06:37:00'
    WHEN account_number = '1010000228' THEN '2024-05-16 06:37:00'
    WHEN account_number = '1010006973' THEN '2024-05-16 06:37:00'
    WHEN account_number = '719770' THEN '2024-05-16 06:37:00'
    WHEN account_number = '719772' THEN '2024-05-16 06:37:00'
    WHEN account_number = '719781' THEN '2024-05-16 06:37:00'
    WHEN account_number = '719790' THEN '2024-05-16 06:37:00'
    ELSE update_date
END
WHERE account_number IN ('50012014','40210042','1010000228','1010006973','719770','719772','719781','719790');

以上的sql我想要根据
WHERE account_number IN ('50012014','40210042','1010000228','1010006973','719770','719772','719781','719790');的顺序进行更新,但是好像这个sql并不一定会根据这个顺序更新。

这个account_number的顺序是 accounts.account_id的升序。

如果我想要按照这个顺序更新的话,我该如何实现呢。非常感谢!

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

file 看文档,应该加个order by 就行了 order by find_in_set(account_number,'50012014,40210042,1010000228,1010006973,719770,719772,719781,719790')

4周前 评论
小猪蹄子 (作者) 4周前
daxiaobuzhaodiao (楼主) 4周前
sunny123456 3周前
sunny123456 3周前
讨论数量: 18
// 创建临时表
            DB::statement("
                CREATE TEMPORARY TABLE temp_order (
                    account_number VARCHAR(20) PRIMARY KEY,
                    balance DECIMAL(10, 2),
                    credit DECIMAL(10, 2),
                    update_order INT
                );
            ");

            // 按顺序插入数据到临时表
            $values = '';
            foreach ($data as $index => $item) {
                $accountNumber = $item['account_number'];
                $balance = $item['balance'];
                $credit = $item['credit'];
                $values .= "('$accountNumber', $balance, $credit, $index + 1),";
            }
            $values = rtrim($values, ',');
            DB::statement("INSERT INTO temp_order (account_number, balance, credit, update_order) VALUES $values;");

            // 使用 JOIN 按顺序更新
            DB::statement("
                UPDATE accounts a
                JOIN temp_order t ON a.account_number = t.account_number
                SET 
                    a.balance = t.balance,
                    a.credit = t.credit,
                    a.update_date = NOW()
            ");

使用以上的临时表能实现么,join的顺序更新,order by不能用,否则数据报错 [1221] Incorrect usage of UPDATE and ORDER BY

4周前 评论
sanders

没碰到过这种需求 但我猜一下:拆多个更新 放一个事务里

4周前 评论
daxiaobuzhaodiao (楼主) 4周前

恕我直言,这种拼接case-when 实现批量更新的,就是纯纯的**。

4周前 评论
dryang (作者) 4周前
陈先生 4周前

除了现在代码的所在地方对accounts的更新外,其他的地方也有
更新操作,其他地方的更新的过程中出现了 dead lock!
所以如果两边都是按照account_id的升序来更新的话,应该会避免掉这个dead lock, 所以我希望粘贴的代码的部分是按照指定的顺序更新,

当然我可以排序之后foreach逐条更新,想请教以下有没有其他的方法可以实现我的需求

4周前 评论

这个批量更新的sql就是坑,不如循环更新

4周前 评论
daxiaobuzhaodiao (楼主) 4周前
yourself

这不是在sql里面变魔术么magic sql。

4周前 评论

file 看文档,应该加个order by 就行了 order by find_in_set(account_number,'50012014,40210042,1010000228,1010006973,719770,719772,719781,719790')

4周前 评论
小猪蹄子 (作者) 4周前
daxiaobuzhaodiao (楼主) 4周前
sunny123456 3周前
sunny123456 3周前

-- 创建一个临时表来存储更新顺序 CREATE TEMPORARY TABLE IF NOT EXISTS update_order ( account_number VARCHAR(255), update_sequence INT );

-- 插入更新顺序 INSERT INTO update_order (account_number, update_sequence) VALUES ('50012014', 1), ('40210042', 2), ...;

-- 使用临时表来控制更新顺序 UPDATE accounts INNER JOIN update_order ON accounts.account_number = update_order.account_number SET accounts.balance = CASE WHEN update_order.account_number = '50012014' THEN 0 -- ... 其他条件 ELSE accounts.balance END, accounts.credit = CASE WHEN update_order.account_number = '50012014' THEN 90 -- ... 其他条件 ELSE accounts.credit END, accounts.update_date = CASE WHEN update_order.account_number = '50012014' THEN '2024-05-16 06:37:00' -- ... 其他条件 ELSE accounts.update_date END WHERE update_order.update_sequence IS NOT NULL ORDER BY update_sequence;

4周前 评论

我看了半天,没看出和这个有什么区别

UPDATE accounts SET balance =  0, credit = 0, update_date = '2024-05-16 06:37:00' WHERE account_number IN ('50012014','40210042','1010000228','1010006973','719770','719772','719781','719790');

UPDATE accounts SET credit = 90 WHERE account_number = '50012014';
4周前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!