MySQL 更新字段的值为当前最大值加1

摘要:在MySQL中,我们在执行update或者insert语句时,可以借助select语句更新一个字段,使其值更新为该字段的最大值加1。

  在《MySQL中自增长序列(@i:=@i+1)的用处及用法》中,介绍了如何在select语句中生成递增序列,《MySQL 把查询结果更新或者插入到新表》介绍了把查询到的多条记录复制到另一张表中,均没有介绍如何更新数据库字段的值为当前最大值加指定步长。所以在本文中,楼兰胡杨将带着大家了解如何更新某个字段的值为当前最大值加指定步长1,步长也可以是其它满足诉求的值。

创建测试表

  使用以下 MySQL 语句创建测试表test并写入三条测试数据:

mysql 复制代码
CREATE TABLE test (
  `id` bigint(20) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
  incr_id INT NOT NULL COMMENT '递增序列',
  creator varchar(30) NOT NULL COMMENT '创建者' 
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '测试表';

INSERT INTO test(incr_id,creator) VALUES (FLOOR(1 + RAND() * 100),"张三");
INSERT INTO test(incr_id,creator) VALUES (FLOOR(1 + RAND() * 100),"张三丰");
INSERT INTO test(incr_id,creator) VALUES (FLOOR(1 + RAND() * 100),"楼兰胡杨");

  表中incr_id用于演示如何更新它的值为其当前最大值加1。当然,令其如主键ID一样支持AUTO_INCREMENT时,可以实现自增长,实现方案非常简单,本文不再赘述。这里主要讲述如何通过update select和insert select实现字段值递增的策略。

update select实现字段递增赋值

  首先使用聚合函数max来计算最大值,然后将其加1。以下SQL将返回test表中incr_id字段的最大值并且加1:

sql 复制代码
SELECT MAX(incr_id)+1 FROM test;

  运行此命令后,将返回一个包含最大值加1的单独的列。接下来,楼兰胡杨将此用作update语句的源值,以下实现方案基于嵌套子查询完成:

mysql 复制代码
UPDATE test 
SET incr_id = (
    SELECT max_incr FROM (
        SELECT MAX(incr_id) + 1 AS max_incr FROM test
    ) AS tmp
)
WHERE id = 3;

  在这个更新DML中,我们在子查询语句中使用聚合函数max计算字段最大值,然后对其最大值加1。与前面的例子一样,WHERE子句用于指定要更新的记录。这个方案因为耗内存、效率低而不适用于批量更新场景,但变量模拟自增方案适用于批量更新或复杂逻辑控制,实现脚本如下:

mysql 复制代码
-- 自定义变量
SET @max_incr = (SELECT MAX(incr_id) + 1 FROM test);
-- 使用变量更新字段
UPDATE test SET incr_id = @max_incr WHERE id = 3;

insert select实现字段递增赋值

  在insert操作中实现字段递增赋值时,也是首先使用聚合函数max来计算最大值,然后将其加1。先介绍一下insert select语法糖:

mysql 复制代码
INSERT INTO target_table (column1, column2, ...)
SELECT value1, value2, ...
FROM source_table_a a JOIN source_table_b b ON a.id = b.a_id
WHERE condition_clause;
  • target_table:用于插入数据的目标表。
  • source_table_a 和 source_table_b:源表,从中选择数据用于插入目标表。可以从多个表中选择数据并插入到目标表中,可以一个表。
  • value1, value2, ...:被插入到目标表的值,既可以是从源表中选择的列,也可以是返回常量的表达式,更可以是一个常量。在编写SELECT语句的时候,可以使用MySQL支持的全部语法。

  下面使用上述语法糖新增一条记录,并且令incr_id字段的新值为其最大值加1:

mysql 复制代码
INSERT INTO test ( `incr_id`, `creator`) 
SELECT IFNULL(max(incr_id), 0) + 1, '递增序列' FROM test;

  IFNULL是专门处理 NULL 值的。若目标表的某些列不允许为 NULL,而假设 SELECT 查询返回 NULL 值,会导致数据插入操作失败。这种书写格式与如下常见VALUES写法区别很大:

myssql 复制代码
INSERT INTO test(incr_id) VALUES (FLOOR(1 + RAND() * 100),"普通insert操作");

小结

  本篇文章的内容基本上就是这些,我们来复盘一下。在本文中,我们提供了一些使用MySQL select语句更新字段的示例,这些DML可以使用聚合函数或者嵌套子查询来计算要设置的新值。各位老铁无论选择哪种方式,都需要确保更新操作仅更新需要更新的记录,否则您可能会无意中、错误地❌更改了整张表的记录。楼兰胡杨还提到,如果您的表包含大量记录,使用SELECT子查询操作可能会比较慢,而借助自定义变量计算最大值的方案可能更轻快。

  欢迎点赞阅读,一同学习交流;若有疑问,请在文章下方留下你的神评妙论!以促使博文💯高质量。

相关推荐
aiks_yuan29 分钟前
MySQL 死锁怎么排查:看懂 INNODB STATUS 死锁日志,先查后插为什么必死锁(MySQL 8.2 实测)
mysql
进击的荆棘4 小时前
MySQL——库的操作
数据库·mysql
计算机毕设定制辅导-无忧学长4 小时前
《基于Spring Boot的迷游哈游戏综合服务平台的开发》
java·vue.js·spring boot·mysql·迷游哈游戏综合服务平台
这个DBA有点耶20 小时前
函数索引的“完全一致”有多苛刻:写法、字符集、类型,差一处就失效
数据库·mysql·代码规范
星恒随风20 小时前
MySQL 从零入门(三):表的约束详解
linux·服务器·数据库·笔记·mysql
杨凯凡1 天前
MySQL 死锁怎么排查?InnoDB 锁等待与 Spring Boot 整事务重试实战
数据库·spring boot·mysql
Decay__1 天前
01_SQLServer 体系架构全解 —— 实例进程、关系引擎、SQLOS 与事务日志深入
运维·数据库·sql·mysql·架构
瑞雪兆丰年兮1 天前
JavaWeb-day07-MySQL(DQL&多表设计)
java·开发语言·数据库·sql·mysql·javaweb·web
FungLeo2 天前
成为全栈·基础补充·数据库迁移与事务:数据结构怎样安全演进
mysql·postgresql·sqlite·数据一致性·数据库事务·数据库迁移·成为全栈
aiks_yuan2 天前
MySQL GROUP BY 很慢怎么优化:加了索引反而从 1 秒变 7 秒,Using temporary 该不该消(MySQL 8.2 实测 400 万行)
mysql