脉脉上看到一个有趣的SQL题目,动手实验了下
题目:如果一个字段加了唯一索引,并且有10行,值分别是1-10。如何用一条sql对这10个数据+1。
准备工作:
-- demo表
drop table if exists `demo`;
create table `demo`(
`id` bigint(20) not null auto_increment comment '主键id',
`num` bigint(20) NOT NULL COMMENT '值',
primary key (`id`),
UNIQUE KEY `uq_num` (`num`)
) engine=innodb auto_increment=1 default charset=utf8mb4 comment='demo表';
-- 插入10条数据
INSERT INTO demo (id,num) VALUES (1,1);
INSERT INTO demo (id,num) VALUES (2,2);
INSERT INTO demo (id,num) VALUES (3,3);
INSERT INTO demo (id,num) VALUES (4,4);
INSERT INTO demo (id,num) VALUES (5,5);
INSERT INTO demo (id,num) VALUES (6,6);
INSERT INTO demo (id,num) VALUES (7,7);
INSERT INTO demo (id,num) VALUES (8,8);
INSERT INTO demo (id,num) VALUES (9,9);
INSERT INTO demo (id,num) VALUES (10,10);
思考:
1、我考虑的是,直接全表更新不带where条件,是否可以避免唯一索引限制?
update demo set num = num+1;
结论是不行,直接报唯一索引冲突。
2、那么还有一种解决办法是,先删除唯一索引,然后更新数据,再把唯一索引加回来。但是这种方法一是繁琐二是也不符合题目要求用一条SQL解决。
3、重新思考一下,其实我们如果能按照num的值从大到小来更新数据,那么其实就不会发生唯一索引冲突。于是我想到在update语句中直接增加order by条件尝试一下。
update demo set num = num+1 order by num desc;
成功了,所以证明,在使用update语句的时候也是可以使用order by的。使用order by之后会按照指定的条件的顺序来更新数据。
查了一下资料:
在Mysql单表更新中,update语句后面可以跟order by条件,指定更新的顺序,如果不写的话则按照数据插入的顺序更新,由于id是自增的,所以我认为默认就是按照主键id小到大的顺序更新。