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

SQL Server插入数据时调用时间类ID生成函数出现重复值如何解决

解决方案

方案1:逐行插入加延迟(仅适合数据量小于100条的场景)

如果需要实现类似循环加sleep的逻辑,可以用游标逐行遍历Users表插入,每次插入后等待1毫秒,避免函数调用频率超过其精度阈值:

DECLARE @UserName VARCHAR(20), @UserAge VARCHAR(50)
-- 声明游标遍历Users表数据
DECLARE user_cursor CURSOR FOR 
SELECT UserName, UserAge FROM USERS

OPEN user_cursor
FETCH NEXT FROM user_cursor INTO @UserName, @UserAge

WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO Contacts (RecID,Name,Age)
    VALUES (dbo.GenerateRecID(), @UserName, @UserAge)
    -- 等待1毫秒,拉开函数调用间隔
    WAITFOR DELAY '00:00:00.001'
    FETCH NEXT FROM user_cursor INTO @UserName, @UserAge
END

CLOSE user_cursor
DEALLOCATE user_cursor

方案2:重试去重机制(比加延迟性能更稳定)

通过TRY CATCH捕获重复键错误,遇到冲突时自动重试生成ID,不需要强制等待,性能优于逐行加延迟方案:

DECLARE @UserName VARCHAR(20), @UserAge VARCHAR(50), @RecID VARCHAR(15), @RetryCount INT

DECLARE user_cursor CURSOR FOR 
SELECT UserName, UserAge FROM USERS

OPEN user_cursor
FETCH NEXT FROM user_cursor INTO @UserName, @UserAge

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @RetryCount = 0
    -- 最多重试3次避免死循环
    WHILE @RetryCount < 3
    BEGIN
        BEGIN TRY
            SET @RecID = dbo.GenerateRecID()
            INSERT INTO Contacts (RecID,Name,Age)
            VALUES (@RecID, @UserName, @UserAge)
            BREAK -- 插入成功跳出重试循环
        END TRY
        BEGIN CATCH
            -- 判断是否为唯一约束/索引冲突错误
            IF ERROR_NUMBER() IN (2601, 2627)
            BEGIN
                SET @RetryCount = @RetryCount + 1
                WAITFOR DELAY '00:00:00.001'
            END
            ELSE
            BEGIN
                -- 非重复类错误直接抛出
                THROW
            END
        END CATCH
    END
    FETCH NEXT FROM user_cursor INTO @UserName, @UserAge
END

CLOSE user_cursor
DEALLOCATE user_cursor

方案3:无游标批量插入优化(性能最优,推荐优先尝试)

不需要游标逐行处理,通过ROW_NUMBER强制每行独立调用ID生成函数,避免批量查询时函数只被调用一次或者调用过快的问题:

INSERT INTO Contacts (RecID, Name, Age)
SELECT fn.GenerateID, u.UserName, u.UserAge
FROM (
    -- 给每行分配唯一行号,强制每行做独立计算
    SELECT UserName, UserAge, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNum
    FROM USERS
) u
CROSS APPLY (
    SELECT dbo.GenerateRecID() AS GenerateID
) fn

如果该方案仍有低概率重复,可以给Contacts表的RecID字段加上唯一约束,配合SQL Server的IGNORE_DUP_KEY索引选项使用,插入时自动忽略重复行后单独补插即可。


内容的提问来源于stack exchange,提问作者Pedro Emilio Vélez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 16:06:03