mysql 插入记录时,主键id的三种处理方式:1、显式设置;2、查询出表中主键ID最大值+1做为添加下一条数据的主键ID;3、表结构设置id自增,插入时不需要设置id值

文章讨论了三种插入数据时处理主键ID的方法:显式设置ID可能会导致冲突,查询最大ID+1可避免冲突但使SQL复杂,而设置ID自增则简化插入操作但可能浪费ID资源。作者建议使用查询最大ID+1的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、显式设置

顾名思义,显式设置就是,把id固定,例如下面的插入sql,id设置为1

1.1、例子

# 实际填充数据
insert into from user(id,name,age,email) 
values(1,'burns',25,'357252539@qq.com');

1.2、优点

简单,

1.3、缺点

如果之前插入过这条记录,或者其他记录的id改为1,那么再次插入时就会报id冲突,这还是一条记录,如果批量插入,都写死id,那么你会痛苦到怀疑人生

2、查询出表中主键ID最大值+1做为添加下一条数据的主键ID

2.1、例子

# 实际填充数据
insert into from user(id,name,age,email) 
values((select max(id)+1 from user u),'burns',25,'357252539@qq.com');

2.2、优点:

1、不会出现id冲突的情况,

2、充分利用id,这点和表结构设置id自增,插入时不需要设置id值有明显区别;这种方式获取id最大值再加一,而表结构设置id自增,插入时不需要设置id值虽然也是自增,但是加入你删除了最新数据,再次插入数据不设置id的时候,你会发现以前使用过的id的数据即使删除了,也不会再使用,而是从从未用过的id开始

2.3、缺点:

为了id的灵活性,牺牲了sql的简洁性。

2.4、常见错误整理

执行语句报错

You can't specify target table 'user' for update in FROM clause

意思是不能再同一个表中查出数据又修改数据,所以要给表取个别名,避免错误。

3、表结构设置id自增,插入时不需要设置id值

如果你的表设置了主键自增,类似如下

那么你在插入数据的时候不用考虑id的值,例如spring boot,mybatis ,jpa框架 调用插入的时候,自动给id复制,不需要显示设置id,这种的话,

插入sql可以简单不设置id的值

3.1、例子

# 实际填充数据
insert into from user(name,age,email) 
values('burns',25,'357252539@qq.com');

3.2、优点

减少sql内容,方便,不会出现id冲突的情况

3.3、缺点

1、需要设置主键id为自增

 2、浪费id资源,即使最新id相关数据插入后又删除,这些id也无法被利用。

综上,建议使用查询出表中主键ID最大值+1做为添加下一条数据的主键ID方式
<think>好的,用户现在的问题是,在使用MySQL的INSERT INTO ... SELECT语句,如何让自主键ID按照指定的。之前他们询问过手动指定自主键的情况,现在需要针对基于查询结果插入数据的情况进行调整。 首先,我需要回顾之前的回答。之前提到两种方法:直接插入指定ID和修改自序列的起始。但现在用户的情况是INSERT INTO ... SELECT,这意味着他们需要从另一个中选择数据插入,同处理自主键的问题。 用户可能遇到的问题是在使用INSERT INTO ... SELECT主键ID无法按预期自,或者他们希望自定义ID的生成方,而是依赖默认的自机制。需要明确的是,在INSERT INTO ... SELECT语句中,通常会手动指定ID,因为SELECT的结果可能包含多行,手动处理每一行的ID会比较困难。 接下来,我需要分析可能的解决方案。一种方法是在插入通过生成ID,比如使用当前最大ID加上行号。这需要结合用户变量或计算来实现。例如,在SELECT子查询中,为每一行生成一个递ID,然后插入到目标中。 另外,可能需要先调整序列的起始,确保后续插入ID从指定开始。例如,使用ALTER TABLE设置AUTO_INCREMENT的,然后在插入指定ID字段,让数据库自动生成。但这种方法适用于批量插入,所有ID都从新的起始开始连续自的情况。 还要考虑用户是否需要每条记录ID都基于某个特定的,比如在原有最大值的基础上加一个固定数。这候需要先查询当前最大ID,然后在SELECT语句中动态计算每个新ID。 需要注意的是,如果在INSERT INTO ... SELECT中同指定了ID字段,并且ID是连续的或存在重复,可能会导致主键冲突。因此,必须确保生成的ID唯一,并且在插入后更新自计数器的,以避免后续插入现冲突。 另外,用户可能需要了解如何动态计算ID,比如使用变量来递。例如,在SELECT语句中使用用户变量,如@rownum,来为每一行生成递ID。这需要正确初始化变量,并在查询中正确应用,以确保每行的ID正确生成。 最后,需要总结这些方法,并提醒用户注意事项,比如并发插入的锁问题,确保自ID的唯一性,以及正确更新自序列的起始,避免后续插入现问题。同,提供相关问题,帮助用户进一步了解相关主题。</think>在MySQL中通过`INSERT INTO ... SELECT`语句插入数据,若需要**自定义自主键ID的生成规则**,需通过构造ID。以下是两种典型场景的解决方案: --- ### 方案1:基于现有数据偏移生成ID **适用场景**:需要从查询结果中批量插入数据,且ID按固定偏移量递(例如原ID+1000) ```sql -- 步骤1:获取当前最大ID设置起点 SET @new_start = (SELECT MAX(id) FROM source_table) + 1000; ALTER TABLE target_table AUTO_INCREMENT = @new_start; -- 步骤2插入指定ID字段 INSERT INTO target_table (col1, col2) SELECT col1, col2 FROM source_table; ``` 此插入记录ID将从`@new_start`开始自动递[^1]。 --- ### 方案2:动态指定每行ID **适用场景**:需要完全自定义ID生成逻辑(例如间戳+序列号) ```sql INSERT INTO target_table (id, col1, col2) SELECT UNIX_TIMESTAMP() * 1000 + (@rownum := @rownum + 1), -- 生成唯一ID(毫秒间戳+序号) col1, col2 FROM source_table CROSS JOIN (SELECT @rownum := 0) r; -- 初始化行号变量 ``` --- ### 核心公 $$ \text{生成规则} = \begin{cases} \text{基础} + \text{行号} & \text{(动态计算)} \\ \text{当前最大ID} + \text{固定偏移} & \text{(批量偏移)} \end{cases} $$ --- ### 注意事项 1. **并发控制**:高并发写入需使用事务锁,避免ID重复 ```sql LOCK TABLES target_table WRITE; -- 执行插入操作 UNLOCK TABLES; ``` 2. **自更新**:手动插入ID后需执行`ALTER TABLE`更新自计数器 3. **ID检查**:确保生成超过`BIGINT UNSIGNED`范围(0~18446744073709551615) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱的叹息

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值