问题: 一张表加了联合唯一索引,然后更新批量数据时报duplicate entry错误。
为了实现前端将文件夹拖动排序功能,并在数据库中更新顺序属性(seq)。

# 文件夹表
CREATE TABLE `folder` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`parent_id` int(11) NULL DEFAULT NULL COMMENT '父级id',
`category` int(11) NULL DEFAULT NULL COMMENT '分类',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名称',
`seq` int(11) NULL DEFAULT NULL COMMENT '排序',
PRIMARY KEY (`id`) USING BTREE
)
联合唯一索引是这三个字段:category_parentid_seq; 意思是在某个分类中,同级的顺序都是唯一(同级就是parent_id一样)。
然后我自己写了个过程函数:如下:
```yaml
# 这里p_id=当前文件夹的id, p_category=分类,p_new_seq=要插入的新位置;
# p_parent_id=父id(如果是同级移动,则不变,如果是放到别的文件夹里头,或者从别的文件夹拖拽到外层时这个p_parent_id需要更新)
CREATE DEFINER=`root`@`localhost` PROCEDURE `update_sequence`(IN `p_id` bigint,IN `p_category` bigint,IN `p_new_seq` int,IN `p_parent_id` int)
BEGIN
DECLARE current_seq INT;
-- 获取当前记录的 seq 值
SELECT seq INTO current_seq
FROM folder
WHERE id = p_id;
-- 为当前记录设置一个临时 seq 值,避免冲突
UPDATE folder
SET seq = -1
WHERE id = p_id;
-- 如果新的 seq 小于当前 seq,则将范围内的 seq 加 1
IF p_new_seq < current_seq THEN
UPDATE folder
SET seq = seq + 1
WHERE category = p_category
AND parent_id = p_parent_id
AND seq >= p_new_seq
AND seq < current_seq;
-- 如果新的 seq 大于当前 seq,则将范围内的 seq 减 1
ELSEIF p_new_seq > current_seq THEN
UPDATE folder
SET seq = seq - 1
WHERE category = p_category
AND parent_id = p_parent_id
AND seq > current_seq
AND seq <= p_new_seq;
END IF;
-- 最后将当前记录的 seq 更新为新的值
UPDATE im_library_folder
SET seq = p_new_seq, parent_id = p_parent_id
WHERE id = p_id;
END
问题出现在递增seq或递减seq时报duplicate entry错误。估计是它依次递增或递减时与原本的数据冲突了,并不是同时执行的。
例如:

如果将id为5的移动到1的位置时,过程函数的顺数如下:
1. 将当前id=5的seq赋值为-1,为了防止冲突;
2.由于新的位置1 < 原来的的位置3,所以1~2之间的seq递增;
这时 id=1的递增后的数据是 category=1,parent_id=0,seq=2,就会跟id=6的数据冲突。这是问题的关键。
我猜问题是出现在这里,所以不知道如何修改。