J'ai une database MSSQL et une application Java Spring qui utilise Spring's Transaction Management.
J'ai une question de "SI NE PAS EXIT, INSERT .." qui est exécuté à partir de plusieurs threads. Pour une raison quelconque, je reçois une violation de contrainte de key primaire, même si je vérifie l'existence avant d'écrire, tout se passe à l'intérieur d'une transaction.
Je voulais savoir quelle était la raison et comment l'éviter.
La requête:
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 pour 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) )
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) )
Votre exemple –
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);