惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
D
DataBreaches.Net
F
Fortinet All Blogs
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
Apple Machine Learning Research
Apple Machine Learning Research
H
Help Net Security
M
MIT News - Artificial intelligence
美团技术团队
人人都是产品经理
人人都是产品经理
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Cloudflare Blog
有赞技术团队
有赞技术团队
L
LangChain Blog
博客园 - Franky
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 【当耐特】
S
SegmentFault 最新的问题
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
Hugging Face - Blog
Hugging Face - Blog
B
Blog
I
InfoQ

博客园 - 冰之玄岩,小小Programmer

程序员效率工具:3秒搞定JSON格式化,这个在线工具真香! 基于grafana+telegraf的服务器监控方案 Sql Server免域,异地备份 TeamCity+Docker k8s 安装步骤 Gitlab使用时的一些注意事项 Docker常用命令 AspNetCore OpenId AspNetCore中的IdentityServer4客户端认证模式实现 AspNet Core 认证 基于TeamCity的asp.net mvc/core,Vue 持续集成与自动部署 使用TFS 自动编译时的一点设置 SQL Server Update 语句使用Nolock 语法 SQL Server 大数据量分页建议方案 页面轮换,ViewFlipper 和 ViewPager 的区别 Mono for android 如何动态添加View,线程内部如何更新UI. C#开发Android环境搭建 SPQuery.ViewAttributes (.Net 3.5Sp1)WebForm使用System.Web.Routing
SQl server 关于重复插入数据的测试
冰之玄岩,小小Programmer · 2015-01-16 · via 博客园 - 冰之玄岩,小小Programmer

最近发布的脚本,有那种防止重复插入数据(包括存在时更新,不存在是插入的处理,判断的方向可能与下面的示例相反)

使用类似下面的 SQL

declare @id int, @value int

if not exists( select * from tb where id = @id )

    insert tb values( @id, @value );

--else

--  update tb set value = @value where id = @id;

或者是使用这种单句的

declare @id int, @value int

insert tb select @id, @value

where not exists( select * from tb where id = @id )

--if @@rowcount = 0

--  update tb set value = @value where id = @id;

或者是用 MERGE 的

declare @id int, @value int

merge tb

    using( values(@id, @value) ) data( id, value)

        on data.id = tb.id

    when not matched by target then insert values( id, value )

    --when matched then update set value = data.value

;

         这几种方法均已说明是无法防止插入重复数据的,只是发生的概率高低有一定的区别而已

针对这种处理需求,我专门做了一些测试,有效的处理方法如下,大家在处理这类问题时,请参考此方法进行:

declare @id int, @value int

begin tran  -- 使查询的更新锁保留到事务结束

if not exists( select * from tb with(holdlock, updlock) where id = @id )

    insert tb values( @id, @value );

--else

--  update tb set value = @value where id = @id;

commit tran

推荐使用这种单句的处理方式,不用显式的事务控制,避免考虑与其他会显式使用事务的地方的交互性

declare @id int, @value int

insert tb select @id, @value

where not exists( select * from tb with(holdlock, updlock) where id = @id )

--if @@rowcount = 0

--  update tb set value = @value where id = @id;

不推荐这种方式,容易出来死锁

declare @id int, @value int

merge tb with(holdlock, updlock)

    using( values(@id, @value) ) data( id, value)

        on data.id = tb.id

    when not matched by target then insert values( id, value )

    --when matched then update set value = data.value

另外,where 这个判断是否重复的条件列,需要创建索引,否则因为锁的关系,数据处理的效率会极低

         如果表中本来就没有重复数据,应该直接建立唯一索引(UNIQUE INDEX),这个对于查询优化有很大的帮助