如何可靠获取序列生成的ID以用于后续INSERT语句?
可靠获取序列生成的插入ID的方法
你遇到的问题根源在于用MAX(id)获取刚插入的ID完全不可靠:
- 并发场景下,其他会话可能在你的
WAITFOR DELAY和SELECT MAX(id)之间向表中插入数据,导致拿到的ID不是你刚插入的那个; - 序列本身可能存在跳号(比如序列配置了缓存,服务重启后未使用的缓存值会被丢弃),此时
MAX(id)会小于你实际使用的序列值。
以下是两种可靠的解决方案:
方法一:提前获取序列值到变量(推荐)
先把序列的下一个值存入变量,再用这个变量完成两个表的插入操作,全程不需要查询表:
DECLARE @ID BigInt -- 先获取序列值到变量 SET @ID = NEXT VALUE FOR transcript.nextid -- 第一个表插入,直接用变量作为ID INSERT INTO transcript.transcript (id, title, departmentId) VALUES (@ID, 'binarySequence', 754) -- 第二个表直接复用同一个变量 INSERT INTO transcript.externalSources (transcriptId, governanceId, hint) VALUES (@ID, 993846122, 'binarySequence');
这种方式完全避免了对表的查询操作,性能更高且绝对可靠,是最推荐的方案。
方法二:使用OUTPUT子句捕获插入的ID
如果需要在插入时直接获取生成的ID,可以用OUTPUT子句把插入的ID捕获到变量中:
DECLARE @ID BigInt INSERT INTO transcript.transcript (id, title, departmentId) -- 将插入的ID输出到变量 OUTPUT inserted.id INTO @ID VALUES (NEXT VALUE FOR transcript.nextid, 'binarySequence', 754) -- 使用捕获到的ID插入第二个表 INSERT INTO transcript.externalSources (transcriptId, governanceId, hint) VALUES (@ID, 993846122, 'binarySequence');
注意:该方案适用于单行插入场景(你的循环中正好是单行),如果是多行插入,需要用表变量来接收OUTPUT的结果。
另外,你原来的WAITFOR DELAY完全没必要,它既不能解决并发问题,还会降低程序执行效率,建议直接移除。
内容的提问来源于stack exchange,提问作者SkyeBoniwell
相关产品推荐
相关产品推荐

