SQL Server 数据库服务器:并行使用存储过程,防止插入相同密钥

8iwquhpp  于 2022-11-21  发布在  其他
关注(0)|答案(1)|浏览(78)

我 有 一 个 SQL Server 存储 过程 , 我 想 从 Spring 启动 时 并行 插入 大量 数据 , 我 必须 确保 三 列 的 复合 值 必须 是 唯一 的 。
我 不 是 SQL Server Maven , 但 AFAIK 有 键 锁 , 这 应该 对 此 有 好处 。 这 三 列 有 索引 。
该 过程 的 工作 原理 如下 : 尝试 找到 一 条 正好 包含 这 三 列 的 记录 。 如果 是 , 则 recordid 将 是 返回 值 。 如果 不 存在 , 则 插入 新 记录 并 返回 其 id 。
我 能 举 个 例子 吗 ?

lnlaulya

lnlaulya1#

第一步是(正如marc上面建议的那样)在这3列的组合上创建一个唯一索引--这不仅提供了确保唯一性所需的完整性结构,而且还允许您高效地查找/搜索具有该值组合的记录。但还有很多其他的问答可以解答。
一旦有了这些,就可以选择如何编写执行所述逻辑的过程。下面列出了两种可以使用的方法-一种是针对插入的值更有可能是唯一/新记录的情况进行更多的优化,另一种是针对插入的值很可能是重复/现有记录的情况进行优化的方法。这些只是两个。

-- Test example table with id and 3 other columns
create table test3 (id int not null primary key clustered identity(1,1), col1 int not null, col2 int not null, col3 int not null);

-- Create a unique compound key on the 3 columns
create unique nonclustered index iux_test3_col1_col2_col3
    on dbo.test3 (col1, col2, col3);

-- Proc that favors/optimizes for the situation where the majority of records are likely to be new/unique records
create procedure dbo.test3_insert_favored
    @col1 int,
    @col2 int,
    @col3 int
as

declare @id int = null;

begin try;
    insert  dbo.test3
            (col1, col2, col3)
    select  @col1, @col2, @col3
    where   not exists
            (
            select  null
            from    dbo.test3 t
            where   t.col1 = @col1
                    and t.col2 = @col2
                    and t.col3 = @col3
            );

    select  @id = scope_identity();
end try
begin catch;
    if error_number() not in(2601, 2627)
    begin;
        throw;
    end;
end catch;

if @id is null
begin;
    select  @id = t.id
    from    dbo.test3 t
    where   t.col1 = @col1
            and t.col2 = @col2
            and t.col3 = @col3;
end;

select  @id as record_id;

go

-- Proc that favors/optimizes for the situation where the majority of records are likely to be repeated/existing records
create procedure dbo.test3_select_favored
@col1 int,
@col2 int,
@col3 int
as

declare @id int = null;

select  @id = t.id
from    dbo.test3 t
where   t.col1 = @col1
        and t.col2 = @col2
        and t.col3 = @col3;

if @id is null
begin;
    begin try;
        insert  dbo.test3
                (col1, col2, col3)
        select  @col1, @col2, @col3;

        select  @id = scope_identity();
    end try
    begin catch;
        if error_number() not in(2601, 2627)
        begin;
            throw;
        end;
    end catch;

end;

if @id is null
begin;
    select  @id = t.id
    from    dbo.test3 t
    where   t.col1 = @col1
            and t.col2 = @col2
            and t.col3 = @col3;
end;

select  @id as record_id;

go

相关问题