SQL Server和重复插入预防

时间:2017-09-22 11:30:06

标签: sql sql-server

我需要确保在并发环境中,我将避免在同一个SQL Server表中重复插入2个。

为了做到这一点,首先,我尝试使用:

执行SELECT
WITH (UPDLOCK, ROWLOCK)

例如:

SELECT * 
FROM Products p WITH (UPDLOCK, ROWLOCK) 
WHERE p.groupId = ?1 AND p.classId = ?2 

在此之后如果上面的select在同一个事务中返回0条记录,我会执行INSERT语句。

这种方法是否可以防止空表上的重复项与p.groupId = ?1 AND p.classId = ?2相同的产品?

如果不是,应该如何实施以避免重复?

2 个答案:

答案 0 :(得分:3)

如果要对表进行插入,并且要确保不超过1行具有相同的groupId和classId,我建议您在创建表时使用Unique约束。例如:

CREATE TABLE Products (
    groupId int NOT NULL,
    classId int NOT NULL,
    ...
    CONSTRAINT UC_GroupClassID UNIQUE (groupId, classId)
);

或者,您可以将表格改为:

ALTER TABLE Products
ADD CONSTRAINT UC_GroupClassID UNIQUE (groupId, classId)

您可以在以下网址找到更多信息:

https://docs.microsoft.com/en-us/sql/relational-databases/tables/create-unique-constraints

https://www.w3schools.com/sql/sql_unique.asp

答案 1 :(得分:1)

根据您的评论,您希望在记录已存在时进行更新。合并声明是为此而设计的。我建议将传入的数据存储到临时表或表变量,然后发出合并。

请参阅此链接以获取我将在此处发布的示例。只需更改表名称和匹配条件。

https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

MERGE Target AS T
USING Source AS S
ON (T.EmployeeID = S.EmployeeID) 
WHEN NOT MATCHED BY TARGET AND S.EmployeeName LIKE 'S%' 
    THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName)
WHEN MATCHED 
    THEN UPDATE SET T.EmployeeName = S.EmployeeName
WHEN NOT MATCHED BY SOURCE AND T.EmployeeName LIKE 'S%'
    THEN DELETE 
OUTPUT $action, inserted.*, deleted.*;