You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用IDENT_CURRENT()在插入时获取ID是否存在并发问题?

问题解答

你的担忧完全合理,多用户并发插入时确实会出现ID赋值错误的情况

IDENT_CURRENT('ExampleTable') 返回的是指定表全局范围内最后生成的标识值,和当前会话、作用域无关。举个实际场景:

  1. 用户A执行INSERT前,获取到的IDENT_CURRENT是100;
  2. 此时用户B先完成插入操作,表的标识值被更新为101;
  3. 用户A的INSERT语句执行时,会用101来拼接ExampleCompositeNumber,但实际插入行的ExampleID是102,直接导致字段值和实际ID不匹配。

而你提到的SCOPE_IDENTITY()确实无法解决这个问题——它返回的是当前作用域内上一次插入的标识值,在这条INSERT语句执行时,当前行的标识值还未生成,所以要么拿到的是之前插入的旧ID,要么就是NULL,完全不符合需求。

正确的实现方案

方案1:使用OUTPUT子句获取当前插入ID

先插入占位值,再通过OUTPUT拿到的真实ID更新字段:

DECLARE @InsertedIDs TABLE (ExampleID int);

-- 先插入空占位
INSERT INTO ExampleTable (ExampleCompositeNumber)
OUTPUT inserted.ExampleID INTO @InsertedIDs
VALUES (NULL);

-- 用真实ID更新复合字段
UPDATE ExampleTable
SET ExampleCompositeNumber = CAST(t.ExampleID AS nvarchar(18)) + '-123345'
FROM ExampleTable t
JOIN @InsertedIDs i ON t.ExampleID = i.ExampleID;

方案2:使用计算列(推荐)

如果ExampleCompositeNumber的规则是固定基于ExampleID生成,直接把它设为计算列,无需手动插入,永远不会出错:

-- 先删除原有字段
ALTER TABLE ExampleTable DROP COLUMN ExampleCompositeNumber;

-- 添加计算列,自动生成符合格式的值
ALTER TABLE ExampleTable
ADD ExampleCompositeNumber AS 
    CAST(ExampleID AS nvarchar(18)) + '-' + RIGHT('000000' + CAST(ABS(CHECKSUM(NEWID())) % 1000000 AS nvarchar(6)),6)
    PERSISTED;

注:这里用NEWID()生成000000-999999的随机数,PERSISTED关键字会把计算结果存储到磁盘,支持创建索引提升查询性能。

方案3:使用AFTER INSERT触发器

创建触发器,插入完成后自动更新字段:

CREATE TRIGGER trg_SetExampleCompositeNumber
ON ExampleTable
AFTER INSERT
AS
BEGIN
    UPDATE ExampleTable
    SET ExampleCompositeNumber = CAST(i.ExampleID AS nvarchar(18)) + '-123345'
    FROM ExampleTable t
    JOIN inserted i ON t.ExampleID = i.ExampleID;
END;

之后插入数据时无需指定ExampleCompositeNumber,触发器会自动生成正确的值。

总结

  • 用IDENT_CURRENT的方式在多用户并发场景下必然会出现ID不匹配的问题,你的担忧完全正确;
  • SCOPE_IDENTITY()无法获取当前插入行的ID,不适用这个场景;
  • 最稳妥的方式是使用计算列(规则固定时),或者用OUTPUT子句、触发器来保证字段值和真实ID的一致性。

内容的提问来源于stack exchange,提问作者Elias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:16:16