今天偶然想起一个UPDATE相关的小问题,正常情况下,如果我们将UPDATE改写成与之对应的SELECT语句,其SELECT查询结果应与UPDATE的目标表存在一对一的关系,例如:
对于UPDATE语句:
UPDATE TB1 SET C2=TB2.C2 FROM TB1 INNER JOIN TB2 ON TB1.C1=TB2.C1
假设TB1中C1为主键,那么改写成对应的SELECT SQL
SELECT TB1.C1,TB1.C2 AS C2_OLD,TB2.C2 AS C2_NEWFROM TB1 INNER JOIN TB2 ON TB1.C1=TB2.C1
以上查询结果应该也可以以C1为主键,即C1在此查询结果中是唯一的。
问题出现了,如果查询结果中C1不唯一,那么更新后的结果会是什么呢?
让我们来测试下,准备测试数据:
CREATE TABLE TB001( C1 INT, C2 INT);GOCREATE TABLE TB002( C1 INT, C2 INT);DELETE FROM TB001DELETE FROM TB002INSERT INTO TB001(C1,C2)SELECT 1,1UNION ALLSELECT 2,1GOINSERT INTO TB002(C1,C2)SELECT 1,3UNION ALLSELECT 1,2UNION ALLSELECT 2,4GOSELECT * FROM TB001SELECT * FROM TB002GOSELECT *FROM TB001 T1 INNER JOIN TB002 T2ON T1.C1=T2.C1
查询结果中C1的记录并不唯一,如果我们对此更新,结果会是什么呢?
UPDATE方式1
--第一种更新UPDATE TB001SET C2=T1.C2*T2.C2FROM TB001 T1 INNER JOIN TB002 T2ON T1.C1=T2.C1--查看执行结果SELECT * FROM TB001
UPDATE方式2
--第二种更新UPDATE TB001SET C2=TB001.C1*T2.C2FROM TB002 T2WHERE TB001.C1=T2.C1--查看执行结果SELECT * FROM TB001
UPDATE方式3
--第三种更新WITH TMP AS( SELECT T1.C1,T1.C2,T1.C2*T2.C2 AS NewC2 FROM TB001 T1 INNER JOIN TB002 T2 ON T1.C1=T2.C1)UPDATE TMPSET C2=NewC2--查看执行结果SELECT * FROM TB001
通过比较,不难看出,对于第一种和第三种方式,TB001中的C1=1的记录只被更新1次,而对于第二种方式来说,该记录被更新2次。
---====================================================================
对于上面的例子,无论那种方式,更新结果都可能不是我们预期的结果,因此我们避免此类操作(尤其是生产环境)。
尽管这些测试没有太多意义,但聊胜于无,供各位看官一看。
BTW:对于三种UPDATE写法,个人偏好第三种,因为可以很容易滴查看SELECT结果集,从而对更新后的结果有一个预期了解,以检查是否满足需求。
--====================================================================
很多人是来看妹子的,我懂你们的。。。
重口难调,你们将就下
新闻热点
疑难解答