sqlserver使用distinct插入数据还出现主键冲突

最近遇到一个用distinct查询数据插入表变量但发生主键冲突的问题
表结构:
create table dis_test(eid bigint not null,
			uid varchar(20) not null,
			name varchar(20)
			status smallint,
			lasttime datetime
constraint [pk_eid] primary key nonclustered(eid asc)
) on [primary]

create clustered index idx_uid on dis_test(uid)
--eid是主键但是非聚集索引,uid为聚集索引

sql:
declare @tmp table (eid bigint primary key)

insert into @tmp
select distinct eid from dis_test (nolock) where status=1
--查询有nolock,允许脏读
出现error:
Violation of PRIMARY KEY constraint 'PK__#A3470C3__B40CC6ED0174E9CC'. Cannot insert duplicate key in object 'dbo.@tmp'.

问题1:为什么有重复数据
问题2:为什么加了distinct还会主键冲突,即distinct失效

重复数据问题

允许脏读,报错的时间点刚好数据发生更新出现了页拆分,每次页拆分会有一半数据到新页,该条数据读到两次(这一点需要了解关于数据页的知识,这里不深入)

distinct失效问题

我们看看查询的执行计划

select distinct eid from dis_test (nolock) where status=1
![--没有聚合,忽略distinct]
(https://img-blog.csdnimg.cn/2020081314443184.png#pic_center)

--换个输出字段对比
select distinct uid from dis_test (nolock) where status=1
![--做了聚合,distinct生效]
(https://img-blog.csdnimg.cn/20200813144725218.png#pic_center)

/*
**在输出字段包含pk的情况下,distinct会忽略,
所以在出现页拆分读了重复数据后,distinct并不会再做去重**
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值