2016-01-11 92 views
1

我有一个MSSQL数据库和一个使用Spring的事务管理的Java Spring应用程序。Spring JDBC“IF NOT EXIST INSERT”主键约束冲突

我有一个查询“IF NOT EXIT,INSERT ..”,它是从多个线程运行的。 由于某种原因,我得到了主键约束违规,即使通过在写入之前检查是否存在,所有情况都发生在事务中。

我想知道这是什么原因,以及如何防止它。

查询:

IF NOT EXISTS (SELECT docId FROM documentStatus WHERE docId='abc') 
BEGIN INSERT INTO documentStatus 
     VALUES ('abc',1,0,NULL) 
END 
ELSE 
BEGIN 
    UPDATE documentStatus SET documentStatus.count=documentStatus.count+1 
     WHERE docId ='abc' 
    END; 

的DDL documentStatus

CREATE TABLE Dss.dbo.docStatus 
    (
     docId NVARCHAR(256), 
     count INT NOT NULL DEFAULT 1, 
     error INT NOT NULL DEFAULT 0, 
     errorMsg NVARCHAR(1024) DEFAULT NULL, 

     CONSTRAINT PK_docStatus PRIMARY KEY (docId ASC) 
    ) 
+0

请提供您的查询 – Devart

+0

欢迎堆栈溢出,请阅读http://stackoverflow.com/help/how-to-ask进而改善你的问题。 –

+0

我添加了查询 –

回答

1

DDL -

USE tempdb 
GO 

IF OBJECT_ID('dbo.docStatus', 'U') IS NOT NULL 
    DROP TABLE dbo.docStatus 
GO 

CREATE TABLE dbo.docStatus (
    docId NVARCHAR(256) PRIMARY KEY, 
    [count] INT NOT NULL DEFAULT 1, 
    error INT NOT NULL DEFAULT 0, 
    errorMsg NVARCHAR(1024) 
) 

你的榜样 -

IF NOT EXISTS (
     SELECT docId 
     FROM docStatus 
     WHERE docId = N'abc' 
    ) 
BEGIN 
    INSERT INTO dbo.docStatus (docId) VALUES (N'abc') 
END 
ELSE 
BEGIN 
    UPDATE docStatus 
    SET [count] += 1 
    WHERE docId = N'abc' 
END 

MERGE声明 -

;WITH cte AS 
(
    SELECT * 
    FROM dbo.docStatus 
    WHERE docId = N'abc' 
) 
MERGE cte t 
USING (
    SELECT docId = N'abc' 
) s ON s.docId = t.docId 
WHEN MATCHED 
    THEN 
     UPDATE SET t.[count] += 1 
WHEN NOT MATCHED BY TARGET 
    THEN 
     INSERT (docId, [count]) 
     VALUES (s.docId, 1); 
+0

另请参阅:https://msdn.microsoft.com/en-us/library/bb510625.aspx – Koshinae

+0

您能详细说明为什么会阻止违规?或为什么它首先发生? –

+0

请为'documentStatus'提供'DDL'索引 – Devart