-- ============================================================ -- 安全生产 - 修复 uk_code 唯一索引导致「第二次软删除同编码」报错 -- 生成时间:2026-10-29 -- -- 现象:巡检点位 PD-001 先被软删一次,之后新建同编码 PD-001 再删除时报 -- Duplicate entry 'PD-001-\x01' for key 'safety_inspection_point.uk_code' -- 接口返回「系统异常」(500) -- -- 原因:uk_code 建在 (code, deleted) 上,deleted 是 bit(1)。 -- 软删除后 deleted=b'1',若历史上已有一条同编码且已软删的记录, -- 第二次软删除就会插入重复的 (code, b'1') 组合,撞唯一键。 -- -- 修复:去掉 (code, deleted) 唯一约束,改成普通索引 idx_code 用于查询; -- 编码唯一性由 Service 层保证(新增/修改时 selectByCode 查活跃记录判重, -- 与 yudao 其它业务表一致,例如 mes_dv_machinery 就没有 code 唯一键)。 -- -- 幂等:先判断索引是否存在再操作,可重复执行 -- ============================================================ DROP PROCEDURE IF EXISTS sp_safety_fix_code_index; DELIMITER $$ CREATE PROCEDURE sp_safety_fix_code_index(IN p_table VARCHAR(64)) BEGIN -- 1. 删掉旧的 (code, deleted) 唯一键 IF EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = p_table AND index_name = 'uk_code') THEN SET @s = CONCAT('ALTER TABLE `', p_table, '` DROP INDEX `uk_code`'); PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st; END IF; -- 2. 补一个普通索引,保证按编码查询的性能 IF NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = p_table AND index_name = 'idx_code') THEN SET @s2 = CONCAT('CREATE INDEX `idx_code` ON `', p_table, '` (`code`)'); PREPARE st2 FROM @s2; EXECUTE st2; DEALLOCATE PREPARE st2; END IF; END$$ DELIMITER ; CALL sp_safety_fix_code_index('safety_inspection_point'); CALL sp_safety_fix_code_index('safety_hazard'); CALL sp_safety_fix_code_index('safety_material'); CALL sp_safety_fix_code_index('safety_work_permit'); CALL sp_safety_fix_code_index('safety_accident'); DROP PROCEDURE IF EXISTS sp_safety_fix_code_index; -- ---------- 校验:确认已无 uk_code,且有 idx_code ---------- SELECT TABLE_NAME, INDEX_NAME, NON_UNIQUE, GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) AS cols FROM information_schema.statistics WHERE table_schema = DATABASE() AND TABLE_NAME LIKE 'safety%' AND INDEX_NAME IN ('uk_code', 'idx_code') GROUP BY TABLE_NAME, INDEX_NAME, NON_UNIQUE ORDER BY TABLE_NAME;