我有一个MSSQL数据库和一个使用Spring的事务管理的Java Spring应用程序。
我有一个" 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;
documentStatus的DDL
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 :(得分: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);