当前位置:首页 > 技术分享

mysql批量更新避免触发唯一索引

admin2个月前 (09-10)技术分享113

方案 1【不改索引,批量禁用 SQL 写法

不改动索引结构,那就需要修改时保证唯一索引组合不冲突。 思路:冻结时,给 name 加特殊标记(例如后缀_disabled_学生id),保证唯一索引字段不会重复。 缺点:原 name 被篡改,后续恢复要把名字还原,适合临时方案。

批量禁用 SQL 示例(批量更新 student_id in (...)):

UPDATE my_student
SET 
    status = 0,
    name = CONCAT(name, '_disabled_', student_id), -- 追加id保证唯一
    update_time = UNIX_TIMESTAMP()
WHERE student_id IN (1001,1002,1003);

恢复启用的时候,需要把 name 再去掉后缀还原:

UPDATE my_student
SET status = 1, name = SUBSTRING_INDEX(name, '_disabled_',1), update_time=UNIX_TIMESTAMP()
WHERE student_id IN (1001,1002,1003);


方案 2 【存储过程(按student_id循环)】

思路:循环逐个更新学生 ID,用异常捕获

  • 尝试只更新 status + update_time

  • 如果捕获唯一索引冲突异常 → 再执行带 name 拼接的更新

优点:业务逻辑干净,大部分学生只改状态;只有冲突的那几条才修改 name 字段。 缺点:需要创建存储过程,批量量大的时候循环会慢一点。

DELIMITER //
CREATE PROCEDURE batch_disable_student(IN ids VARCHAR(1000))
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE v_student_id INT;
    DECLARE CONTINUE HANDLER FOR 1062 -- 唯一索引冲突错误码
    BEGIN
        -- 冲突时:拼接name后缀再更新
        UPDATE my_student
        SET status = 0,
            name = CONCAT(name, '_disabled_', v_student_id),
            update_time = UNIX_TIMESTAMP()
        WHERE student_id = v_student_id;
    END;

    -- 拆分ids字符串,循环处理每个student_id
    WHILE i <= LENGTH(ids) DO
        SET v_student_id = SUBSTRING_INDEX(SUBSTRING_INDEX(ids, ',', i), ',', -1);
        -- 先尝试只更新状态
        UPDATE my_student
        SET status = 0, update_time = UNIX_TIMESTAMP()
        WHERE student_id = v_student_id;
        SET i = i + 1;
    END WHILE;
END //
DELIMITER ;

调用示例:

CALL batch_disable_student('1001,1002,1003');

⚠️ 注意:字符串拆分方式简单,ID 数量多建议改用临时表方式,避免字符串长度限制。

存储过程(按 class_id 循环)

DELIMITER //
CREATE PROCEDURE batch_disable_student_by_class(IN class_ids VARCHAR(1000))
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE v_class_id INT;
    DECLARE v_student_id INT;
    -- 唯一索引冲突捕获句柄
    DECLARE CONTINUE HANDLER FOR 1062
    BEGIN
        -- 冲突:修改姓名+标记
        UPDATE my_student
        SET status = 0,
            name = CONCAT(name, '_disabled_', v_student_id),
            update_time = UNIX_TIMESTAMP()
        WHERE student_id = v_student_id;
    END;

    -- 循环拆分 class_ids
    WHILE i <= LENGTH(class_ids) DO
        SET v_class_id = SUBSTRING_INDEX(SUBSTRING_INDEX(class_ids, ',', i), ',', -1);
        
        -- 游标遍历当前班级下待禁用学生(这里自行加WHERE条件,示例:status=1正常学生)
        BEGIN
            DECLARE done INT DEFAULT 0;
            DECLARE cur CURSOR FOR 
                SELECT student_id FROM my_student 
                WHERE class_id = v_class_id AND status = 1;
            DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
            
            OPEN cur;
            FETCH cur INTO v_student_id;
            WHILE done = 0 DO
                -- 优先尝试:只改状态,不改姓名
                UPDATE my_student
                SET status = 0, update_time = UNIX_TIMESTAMP()
                WHERE student_id = v_student_id;
                
                FETCH cur INTO v_student_id;
            END WHILE;
            CLOSE cur;
        END;

        SET i = i + 1;
    END WHILE;
END //
DELIMITER ;

调用示例

禁用 class_id=10,20,30 下面所有正常状态学生

CALL batch_disable_student_by_class('10,20,30');


扫描二维码推送至手机访问。

版权声明:本文由小刚刚技术博客发布,如需转载请注明出处。

本文链接:https://blog.bitefu.net/post/763.html

标签: mysql
分享给朋友:

“mysql批量更新避免触发唯一索引” 的相关文章

VirtualXposed 不支持32位应用 32位无法安装问题解决办法

VirtualXposed 不支持32位应用 32位无法安装问题解决办法

VirtualXposed 是基于VirtualApp 和 epic 在非ROOT环境下运行Xposed模块的实现(支持5.0~10.0)。与 Xposed 相比,目前 VirtualXposed 有…

PHP AES加解密 (ECB模式/sha1prng算法/PKCS5Padding和PKCS7Padding补码) ECB 模式不需求设置 iv

php7+ 版本/**  * [AesSecurity aes加密,支持PHP7+]  * 算法模式:ECB  * 密钥长度:128  * 补…

微软Windows 10升级密钥(例如家庭版升级为企业版) 不能用于激活系统

微软Windows 10升级密钥(例如家庭版升级为企业版) 不能用于激活系统

下面的密钥,是微软官方提供的,仅能用于Windows10系统版本的升级,比如从家庭版升级为专业版、专业版升级为企业版等。升级密钥不能用于激活系统,激活需要KMS或者数字权利,由于涉及到版权问题,在此不宜分享,请大家自行查找激活相关的内容。准…

遭遇国外ip抓取或攻击怎么办一招解决禁止海外IP访问

遭遇国外ip抓取或攻击怎么办一招解决禁止海外IP访问

究发现很多网站被攻击都是来自海外的肉鸡,所以禁掉海外IP访问网站也是不错的防护手段,而且国内网站几乎很少有国外用户访问,称之为大局域网也不为过。今天主机吧来教大家如何利用域名解析禁止掉海外IP访问网站。绝大多数域名解析服务商都是提供电信联通…

安卓模拟器连接端口 及常用命令

下面是我总结和测试通过的:有的是搜集来的模拟器名称                     &nbs…

【不忘初心】19041/19042/19043(20H1,20H2,21H1)告别繁琐 一键替换太阳谷图标 一键恢复原版图标 一键恢复文件夹预览

【不忘初心】19041/19042/19043(20H1,20H2,21H1)告别繁琐 一键替换太阳谷图标 一键恢复原版图标 一键恢复文件夹预览

一键替换太阳谷图标,一键恢复原版图标,注意是一键!!!  太阳谷图标确实很好看,很新颖 !论坛也有相关替换教程,有的需要改权限,有的需要PE下替换,有的还得重启,搞不好很容易翻车,有些小白同学只能望梅止渴,今天以上统统告…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。