sql-server - 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
谁能建议两者中哪一个更好?
谢谢
解决方案
您的第二种方法有缺陷,您检查'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)
.
推荐阅读
- python - 有没有办法在 Visual Studio Code(特别是 Python)的“输出”通道中输入
- protocol-buffers - protoc go_package 的正确格式?
- c++ - 过滤掉不必要的词(即没有内涵的词)
- python - 使用 docutils 解析和编写 RST
- javascript - 节点mysql查询在最初正确记录后返回未定义的变量
- sql-server-2016 - SQL Server 2016,Web 版复制选项
- azure-data-explorer - Kusto:将所有列投影为字符串
- python - 在python多处理中使用进程之间的共享值终止循环
- firebase - 使用 Firebase 在 Flutter 中处理 iOS 和 Android 通知负载
- haskell - Haskell:如何检测“惰性内存泄漏”