只有在单个语句中不存在记录时才能INSERT吗?

fli*_*p66 0 sql sql-server sql-server-2012

我必须把值插入到表与这些列:Id MasterId ZipCode Locality Value,CreatedTime,UpdatedTime

这3列定义了一个唯一值: MasterId ZipCode Locality

这些列上的数据库没有唯一约束,但我需要确保2个用户无法输入相同的数据.我无法更改T-SQL数据库架构.

当前的SQL:

INSERT INTO dbo.Carrier VALUES (?, ?, ?, ?, ?, GETDATE(), GETDATE())
Run Code Online (Sandbox Code Playgroud)

我的SQL更改:

IF NOT EXISTS
(
    SELECT TOP 1 *
    FROM dbo.Carrier
    WHERE MasterId = ?
    AND ZipCode = ?
    AND Locality = ?
)
BEGIN
    INSERT INTO dbo.Carrier VALUES (?, ?, ?, ?, ?, GETDATE(), GETDATE())
END
Run Code Online (Sandbox Code Playgroud)

这些更改适用于标准用户输入,但也有一个服务同时插入许多条目.有时,此服务将尝试以多线程方式插入数千个相同的唯一行,并且SQL具有竞争条件,因为它不是一个语句.这允许在同时执行2个语句时输入重复项.

有没有办法只在单个语句中不存在记录时插入?

我在UPDATE上没有这个问题,因为我可以做一个UpdatedTime没有改变的地方.

Gor*_*off 6

我会使用not exists以下单一语句执行此操作:

insert into dbo.Carrier (masterid, zipcode, locality, . . . )
    select v.*
    from (values (?, ?, ?, ... ), (?, ?, ?, ...)) v(masterid, zipcode, locality, . . .)
    where not exists (select 1
                      from dbo.Carrier c
                      where c.masterid = v.masterid and c.zipcode = v.zipcode and c.locality = v.locality
                     );
Run Code Online (Sandbox Code Playgroud)

编辑:

如果要保护数据库以满足竞争条件,则应该让数据库进行保护.添加唯一索引/约束(masterid, zipcode, locality).然后你应该忽略任何违反约束的错误.