日期:2014-05-18  浏览次数:20483 次

请大家看看这样更新后的结果是什么
SQL code

--1.请大家分别在2000与2005中运行,看看#t1表中的fQty的值是多少
--2.为什么会有这种差别呢

create table #t1(fCode varchar(10),fQty int)
create table #t2(fCode varchar(10),fQty int)

insert into #t1(fCode,fQty)
select 'A',0


insert into #t2(fCode,fQty)
select 'A',5 union all
select 'A',4 union all
select 'A',8 union all
select 'A',1 union all
select 'A',3

update a set a.fQty=b.fQty
from #t1 a join #t2 b on a.fCode=b.fCode

select * from #t1




------解决方案--------------------
SQL code

create table #t1(fCode varchar(10),fQty int)
create table #t2(fCode varchar(10),fQty int)

insert into #t1(fCode,fQty)
select 'A',0


insert into #t2(fCode,fQty)
select 'A',5 union all
select 'A',4 union all
select 'A',8 union all
select 'A',1 union all
select 'A',3

update a set a.fQty=b.fQty
from #t1 a join #t2 b on a.fCode=b.fCode

select * from #t1
/*
fCode      fQty
---------- -----------
A          5
*/
drop table #t1
drop table #t2
/*
Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86) 
*/

------解决方案--------------------
这样子更新是确定不了什么的,2000和2005的排序规则可能有异同的地方,而且更新的是多对一,本身是不确定的。没什么意义。
------解决方案--------------------
1表对应b表的多条记录,这样更新没什么意义,排序不一样,结果就不一样
------解决方案--------------------
SQL code
--2000的运行结果如下
fCode      fQty        
---------- ----------- 
A          3

--分析::a的fCode和b的五个fCode都匹配,
--但更新时是按顺序取最后一个,类似select @a=name from tb,结果@a肯定是tb表的最后一个name

------解决方案--------------------
SQL的执行顺序 从左到右,依次更新,变量优先
------解决方案--------------------
用UPDATE的方式更新数据本身就有不确定性,看一下计划就知道了
SQL code
IF OBJECT_ID('TEMPDB..#T1') IS NOT NULL DROP TABLE #T1
IF OBJECT_ID('TEMPDB..#T2') IS NOT NULL DROP TABLE #T2
GO
create table #t1(fCode varchar(10),fQty int)
create table #t2(fCode varchar(10),fQty int)

insert into #t1(fCode,fQty)
select 'A',0


insert into #t2(fCode,fQty)
select 'A',5 union all
select 'A',4 union all
select 'A',8 union all
select 'A',1 union all
select 'A',3
GO
SET SHOWPLAN_TEXT ON
GO
update a set a.fQty=b.fQty
from #t1 a join #t2 b on a.fCode=b.fCode
GO
SET SHOWPLAN_TEXT OFF
GO
/*
  |--Table Update(OBJECT:([tempdb].[dbo].[#t1] AS [a]), SET:([tempdb].[dbo].[#t1].[fQty] as [a].[fQty] = [tempdb].[dbo].[#t2].[fQty] as [b].[fQty]))
       |--Top(ROWCOUNT est 0)
            |--Stream Aggregate(GROUP BY:([Bmk1000]) DEFINE:([b].[fQty]=ANY([tempdb].[dbo].[#t2].[fQty] as [b].[fQty])))
                 |--Nested Loops(Inner Join, WHERE:([tempdb].[dbo].[#t2].[fCode] as [b].[fCode]=[tempdb].[dbo].[#t1].[fCode] as [a].[fCode]))
                      |--Table Scan(OBJECT:([tempdb].[dbo].[#t1] AS [a]))
                      |--Table Scan(OBJECT:([tempdb].[dbo].[#t2] AS [b]))
*/

------解决方案--------------------


等同於

SQL code
update Top (1) a set FQty=b.FQty from #t1 a join #t2 b on a.fCode=b.fCode

------解决方案--------------------
两个表没有聚集索引,是堆结构,也就是说数据在堆中的顺序是随机的,所以数据被访问的顺序也是随机的。跟2000和2005没关系。你找两台sql server 2000,也可能产生不一样的结果,数据量大的时候更容易重现这种现象。
------解决方案--------------------