我总是使用类似下面的东西来实现它:
INSERT INTO TheTable
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WHERE
PrimaryKey = @primaryKey)
Run Code Online (Sandbox Code Playgroud)
...但是一旦加载,就会发生主键违规.这是唯一插入此表的语句.那么这是否意味着上述陈述不是原子的?
问题是,这几乎不可能随意重建.
也许我可以将其更改为以下内容:
INSERT INTO TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
WHERE
PrimaryKey = @primaryKey)
Run Code Online (Sandbox Code Playgroud)
虽然,也许我使用错误的锁或使用过多的锁定或其他东西.
我在stackoverflow.com上看到了其他问题,其中答案是建议"IF(SELECT COUNT(*)... INSERT"等),但我总是在(可能是不正确的)假设单个SQL语句是原子的.
有没有人有任何想法?
我想做一个UPSERT的SELECT/INSERT版本.以下是现有代码的模板:
// CREATE TABLE Table (RowID INT NOT NULL IDENTITY(1,1), RowValue VARCHAR(50))
IF NOT EXISTS (SELECT * FROM Table WHERE RowValue = @VALUE)
BEGIN
INSERT Table VALUES (@Value)
SELECT @id = SCOPEIDENTITY()
END
ELSE
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE)
Run Code Online (Sandbox Code Playgroud)
将从许多并发会话中调用该查询.我的性能测试表明它会在特定负载下持续抛出主键违规.
是否有一种高并发方法可以使此查询保持性能,同时仍然避免插入已存在的数据?
t-sql sql-server concurrency design-patterns sql-server-2008
互联网上有很多关于这个常见"问题"的信息.
解决方案如:
IF NOT EXISTS() BEGIN INSERT INTO (...) END
Run Code Online (Sandbox Code Playgroud)
在我看来并不是线程安全的,你可能会同意.
但是你能否确认将exists存入一个select的where子句会解决sql引擎中最高并发性的问题?够了吗?
insert into Table (columns)
select column1, column2, column3
where not exists (select top 1 1 from Table where something)
Run Code Online (Sandbox Code Playgroud)
应该在那里还添加了一些更高的事务级别,还是可以在默认的一个上执行:commit?
这会在未提交的水平下工作吗?
谢谢!
//稍后添加
我可以假设两个sql'都是正确的:
1)设置事务隔离级别可重复读取
IF NOT EXISTS() BEGIN INSERT INTO (...) END
Run Code Online (Sandbox Code Playgroud)
2)设置事务隔离级别可重复读取
insert into Table (columns)
select column1, column2, column3
where not exists (select top 1 1 from Table where something)
Run Code Online (Sandbox Code Playgroud) 我正在使用SQL Server 2008.
我NVARCHAR(MAX)
在表中有一个列,我想确保它是唯一的.该表有600,000条记录,每天增加50,000条记录.
目前在向表中添加项目之前,我检查它是否存在于表中,如果不存在,我将其插入.
IF NOT EXISTS (SELECT * FROM Softs Where Title = 'example example example.')
BEGIN
INSERT INTO Softs (....)
VALUES (...)
END
Run Code Online (Sandbox Code Playgroud)
我在Title列上没有索引
最近,我在向桌子插入物品时开始超时.
什么是维持独特的正确方法?
如果真的有帮助我可以将NVARCHAR(MAX)更改为NVARCHAR(450)
sql-server ×4
concurrency ×2
sql ×2
t-sql ×2
.net ×1
exists ×1
insert ×1
locking ×1
transactions ×1