首页 > 解决方案 > IF NOT EXISTS VS @@ROWCOUNT = 0 哪种方法适合插入记录

问题描述

如果记录不存在,我需要将记录插入表中。我有下表

CREATE TABLE #EMP 
(
    EmpID INT IDENTITY(1, 1),
    EmpName VARCHAR(100),
    Designation VARCHAR(10)
)

INSERT INTO #EMP (EmpName, Designation)
VALUES ('Ramesh', 'Teamlead'), 
       ('Suresh', 'Manager')

现在我想通过检查记录是否存在来插入记录

我可以选择以下两种方法之一:

方法#1:

DECLARE @EmpID INT

SELECT @EmpID = EmpID
FROM #EMP 
WHERE EmpName = 'Ramesh' AND Designation = 'Teamlead'

IF @@ROWCOUNT = 0
    INSERT INTO #EMP (EmpName, Designation)
    VALUES ('Ramesh', 'Teamlead')

方法#2:

IF NOT EXISTS (SELECT NULL 
               FROM #EMP 
               WHERE EmpName = 'Ramesh' AND Designation = 'Teamlead')
BEGIN
    INSERT INTO #EMP (EmpName, Designation)
    VALUES ('Ramesh', 'Teamlead')
END

谁能建议两者中哪一个更好?

谢谢

标签: sql-servertsql

解决方案


您的第二种方法有缺陷,您检查'Ramesh'但如果它们也不存在INSERT 'Suresh',谁可能已经存在。

我个人建议在一份声明中完成所有工作。像这样的东西:

INSERT INTO #EMP (EmpName, Designation)
SELECT EmpName,
       Designation
FROM (VALUES('Ramesh','Teamlead'),
            ('Suresh','Manager'))V(EmpName, Designation)
WHERE NOT EXISTS (SELECT 1
                  FROM #EMP E
                  WHERE E.EmpName = V.EmpName
                    AND E.Designation = V.Designation);

正如@DanGuzman所提到的,这确实会带来一个问题(就像你的一样),它可能会遭受竞争条件(尽管使用本地临时表这不会成为问题)。因此,一种方法是在语句之​​前将隔离级别更改为可序列化:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

或者,您可以使用HOLDLOCK表中的提示NOT EXISTS,即使用WITH (HOLDLOCK).


推荐阅读