SQL Server 错误违反PRIMARY KEY约束'PK__#documen__16C6400F5AFF46C6',无法在对象中插入重复的键

zkure5ic  于 2023-01-20  发布在  其他
关注(0)|答案(1)|浏览(82)

我有一个存储过程,它给我一个错误
“违反主键约束”PK__#documen__16C6400F5AFF46C6“。无法在对象”dbo.#documents“中插入重复的键。重复的键值为(78812702)”
以下是存储过程的简化版本。在将数据添加到表#文档之前,需要进行唯一性检查,但我仍然遇到了这个错误。很奇怪。有人遇到过这样的问题吗?问题的原因可能是什么?

drop table #documents
drop table #documentstest
begin
set  nocount on;

    BEGIN TRY  
    CREATE table #documents (VersionId int primary key, 
                                 MasterId int, 
                                 CadName varchar(160), 
                                 Revision varchar(10),
                                 Iteration int,
                                 LifecycleState varchar(20),
                                 ModifiedOn datetime,
                                 Lvl int)

    CREATE table #documentstest (Documentid int primary key, 
                                 MasterId int, 
                                 CadName varchar(160), 
                                 Revision varchar(10),
                                 Iteration int,
                                 LifecycleState varchar(20),
                                 ModifiedOn datetime,
                                 Lvl int)

    INSERT INTO #documents (VersionId, MasterId, CadName, Revision, Iteration, LifecycleState, ModifiedOn, Lvl)
    VALUES ('12345', '8945656', 'test.prt', 'A', 1, 'study', '2022-12-12', 1);

    INSERT INTO #documentstest (Documentid, MasterId, CadName, Revision, Iteration, LifecycleState, ModifiedOn, Lvl)
    VALUES ('123456', '435345', 'test1.prt', 'A', 1, 'study', '2022-12-12', 1);

    INSERT INTO #documentstest (Documentid, MasterId, CadName, Revision, Iteration, LifecycleState, ModifiedOn, Lvl)
    VALUES ('12345', '689789', 'test2.prt', 'A', 1, 'study', '2022-12-12', 1);

    DECLARE @lvl int
    SET @lvl=0

    declare @Rownum  int
    set @Rownum=1

    DECLARE @rowCount int

    DECLARE @publishError bit
    SET @publishError=0

    PRINT CONVERT(VARCHAR(25), GETDATE(), 21) + ' - LoopB - Level = ' + CAST(@lvl AS VARCHAR(25))

    --select distinct VersionId from #documents

    PRINT CONVERT(VARCHAR(25), GETDATE(), 21) + ' - try adding data' 

    BEGIN
        INSERT  #documents
        SELECT distinct Documentid, MasterId, CadName, Revision, Iteration, LifecycleState, ModifiedOn, lvl FROM #documentstest
        where @Rownum=1
        and Documentid not in (select distinct VersionId from #documents) -- added condiotion to check existing key
        SET @rowCount = 5
        PRINT CONVERT(VARCHAR(25), GETDATE(), 21) + ' - done with adding' 
    END

    PRINT CONVERT(VARCHAR(25), GETDATE(), 21) + ' - executing after issue'
    INSERT INTO #documents (VersionId, MasterId, CadName, Revision, Iteration, LifecycleState, ModifiedOn, Lvl)
    VALUES ('1238', '689789', 'test2.prt', 'A', 1, 'study', '2022-12-12', 1);

    select * from #documents 
    select * from #documentstest

    END TRY
    BEGIN CATCH 
    THROW;
    PRINT CONVERT(VARCHAR(25), GETDATE(), 21) + ' Caught Exception' 
    --  set @publishError=1
    --select * from #documents
    --select * from #documentstest
    --PRINT CONVERT(VARCHAR(25), GETDATE(), 21) + ' - executing after issue'
    END CATCH

PRINT CONVERT(VARCHAR(25), GETDATE(), 21) + ' Executing the END' + CAST(@publishError AS VARCHAR(25))
end

想要解决此问题,但无法理解为什么会出现此问题,因为在添加之前需要进行唯一检查

e4yzc0pl

e4yzc0pl1#

它会带来主键约束和死锁问题
这似乎是并发问题。SERIALIZABLE(HOLDLOCK)将停止争用条件。UPDLOCK将停止死锁。对吞吐量不利!

INSERT INTO #documents
SELECT Documentid, MasterId, CadName, Revision, Iteration, LifecycleState, ModifiedOn, lvl
FROM #documentstest T
WHERE NOT EXISTS
(
    SELECT 1
    FROM #documents D WITH (UPDLOCK, SERIALIZABLE)
    WHERE D.VersionId = T.Documentid
);

相关问题