SQL server update执行顺序

dsgllxy 2017-10-21 09:56:10
---示例数据

--drop table [TempOrder]
--------
CREATE TABLE [dbo].[TempOrder]([FEntryID] [int] IDENTITY(1,1) NOT NULL,FInterID int not null default(0),[FItemID2] [int] NOT NULL
CONSTRAINT [PK_TEMP_Order] PRIMARY KEY CLUSTERED
(
[FEntryID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
-------
insert into TempOrder(FInterID,FItemID2) values(10,256)
------------------------------
--drop table [TEST]
------------------------------
CREATE TABLE [dbo].[TEST](FID INT IDENTITY(1,1),FInterID int not null default(0),FItemID INT NOT NULL DEFAULT(0) )
-------
insert into TEST(FInterID,FItemID) values (10,300)
insert into TEST(FInterID,FItemID) values (10,400)
-------
update T1 set T1.FItemID2=T2.FItemID
from TempOrder T1
join TEST T2
on T1.FInterID=T2.FInterID
-------
select * from TempOrder
-------
--TempOrder.FItemID2=300,为什么? update执行顺序是什么?
...全文
790 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
dsgllxy 2017-10-23
  • 打赏
  • 举报
回复
好象与联接表TEST的 主键排序没什么关系,因为返回值在主键排序前后都有记录。背后一定存在着如何排序与返回结果值的问题;不大可能是随机的。
dsgllxy 2017-10-23
  • 打赏
  • 举报
回复
@ayalicer: 如果是自己写的代码,完全可以避免产生这样的问题;通过对XXX系统一周的跟踪测试,发现原来的问题是出在这个地方;所以才想了解一下SQL深层次的运作机制; 谢谢ayalicer的分析跟进,也不太明白主键与ON的条件不一致会不会造成影响。
xiaoxiangqing 2017-10-23
  • 打赏
  • 举报
回复
更新是不能指定顺序吧
  • 打赏
  • 举报
回复
但是感觉最好还是有个id行 进行开窗中 order by 比较好
  • 打赏
  • 举报
回复
如果你想要满足匹配条件的最后一行 进行对TempOrder更新 可以这样
update T1 set T1.FItemID2=T2.FItemID 
output deleted.*,inserted.*  -- 加这行
from TempOrder T1
join (select * from(select *,rowid=count(1)over(partition by FInterID)+1-row_number()over(partition by FInterID order by (select 1)) from TEST)t) T2
on T1.FInterID=T2.FInterID and rowid=1
FEntryID	FInterID	FItemID2	FEntryID	FInterID	FItemID2
1	10	300	1	10	400
dsgllxy 2017-10-23
  • 打赏
  • 举报
回复
在实务中遇到的情况是:表TEST设置了主键执行update时,我猜想会根据表TEST的主键排序后返回结果集中的第一个(也就是300这个行次),而事实上结果不是我想像的,真会发生返回400这个行次,测试用的数据行次在1百万+。
  • 打赏
  • 举报
回复
只执行遇到满足匹配条件的第一行,至于怎么算第一行,不同版本 可能还不一定一致
dsgllxy 2017-10-23
  • 打赏
  • 举报
回复
@ayalicer:根据你的指示测试正如你所述,那为什么insert不是400这一行,而是300行项呢?
  • 打赏
  • 举报
回复
你原先的update 语句加两行 你就知道,原表删除了什么,有插入了什么(注:update 其实是 delete 和insert 2个动作)
update T1 set T1.FItemID2=T2.FItemID 
output deleted.*,inserted.*  -- 加这行
from TempOrder T1
join TEST T2
on T1.FInterID=T2.FInterID
FEntryID	FInterID	FItemID2	FEntryID	FInterID	FItemID2
1	10	256	1	10	300
dsgllxy 2017-10-23
  • 打赏
  • 举报
回复
@一楼ayalicer: 那是不是说在结果集中随机选一个数值----只要满足条件就去执行更新了,听起来觉的很疯狂。 @二楼sinat_28984567: update关联条件为一对多的关系根据我的理解:返回字段TempOrder.FItemID2的值可能为300或者是400;也就是说此SQL语句在此肯定存在一定的机制,为什么返回值不是400。此过程中计算的逻辑关系是什么? 网上讲了很多Select语句计算的顺序关系,但少看到类似update语句在此场景的计算逻辑关系。
  • 打赏
  • 举报
回复
他意思为什么不是400 匹配满足条件的有两行
dsgllxy 2017-10-23
  • 打赏
  • 举报
回复
看了版主推荐的链接,是问题的正解。谢谢版主。
OwenZeng_DBA 2017-10-23
  • 打赏
  • 举报
回复
引用 9 楼 dsgllxy 的回复:
在实务中遇到的情况是:表TEST设置了主键执行update时,我猜想会根据表TEST的主键排序后返回结果集中的第一个(也就是300这个行次),而事实上结果不是我想像的,真会发生返回400这个行次,测试用的数据行次在1百万+。
关于这个问题官网有说明过。这个数字是300 还是400是不确定的。所以最好不要这么去使用.从程序逻辑上去避免这种写法 https://docs.microsoft.com/en-us/sql/t-sql/queries/update-transact-sql
  • 打赏
  • 举报
回复
update 只更新 满足条件第一行
二月十六 2017-10-22
  • 打赏
  • 举报
回复
-TempOrder.FItemID2=300,为什么? update执行顺序是什么?
什么意思?

22,210

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧