今天偶然想起一个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_NEW
FROM TB1
INNER JOIN TB2
ON TB1.C1=TB2.C1

以上查询结果应该也可以以C1为主键,即C1在此查询结果中是唯一的。

问题出现了,如果查询结果中C1不唯一,那么更新后的结果会是什么呢?

让我们来测试下,准备测试数据:

CREATE TABLE TB001
(
C1 INT,
C2 INT
);
GO
CREATE TABLE TB002
(
C1 INT,
C2 INT
); DELETE FROM TB001
DELETE FROM TB002 INSERT INTO TB001(C1,C2)
SELECT 1,1
UNION ALL
SELECT 2,1 GO
INSERT INTO TB002(C1,C2)
SELECT 1,3
UNION ALL
SELECT 1,2
UNION ALL
SELECT 2,4 GO
SELECT * FROM TB001
SELECT * FROM TB002
GO
SELECT *
FROM TB001 T1
INNER JOIN TB002 T2
ON T1.C1=T2.C1

查询结果中C1的记录并不唯一,如果我们对此更新,结果会是什么呢?

UPDATE方式1

--第一种更新
UPDATE TB001
SET C2=T1.C2*T2.C2
FROM TB001 T1
INNER JOIN TB002 T2
ON T1.C1=T2.C1 --查看执行结果
SELECT * FROM TB001

UPDATE方式2

--第二种更新
UPDATE TB001
SET C2=TB001.C1*T2.C2
FROM TB002 T2
WHERE 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 TMP
SET C2=NewC2
--查看执行结果
SELECT * FROM TB001

通过比较,不难看出,对于第一种和第三种方式,TB001中的C1=1的记录只被更新1次,而对于第二种方式来说,该记录被更新2次。

---====================================================================

对于上面的例子,无论那种方式,更新结果都可能不是我们预期的结果,因此我们避免此类操作(尤其是生产环境)。

尽管这些测试没有太多意义,但聊胜于无,供各位看官一看。

BTW:对于三种UPDATE写法,个人偏好第三种,因为可以很容易滴查看SELECT结果集,从而对更新后的结果有一个预期了解,以检查是否满足需求。

--====================================================================

很多人是来看妹子的,我懂你们的。。。

重口难调,你们将就下

曲演杂坛--Update的小测试的更多相关文章

  1. 曲演杂坛--一条DELETE引发的思考

    原文:曲演杂坛--一条DELETE引发的思考 场景介绍: 我们有一张表,专门用来生成自增ID供业务使用,表结构如下: CREATE TABLE TB001 ( ID ,) PRIMARY KEY, D ...

  2. 曲演杂坛--为什么SELECT语句会被其他SELECT阻塞?

    很多刚入门的DBA在捕获阻塞得时候,会问这么一个问题“为什么这个SELECT语句被那个SELECT语句阻塞了,难道不是共享锁么?” 让我们来做个小测试,首先准备一些测试数据: --========== ...

  3. 曲演杂坛--使用TRY CATCH应该注意的一个小细节

    群里一个朋友遇到一个TRY CATCH的小问题,测试后发现是自己从来没有考虑的情况,写篇blog加深下印象 --============================================ ...

  4. 曲演杂坛--使用CTE时踩的小坑:No Join Predicate

    在一次系统优化中,意外发现一个比较“坑”的SQL,拿出来供大家分享. 生成演示数据: --====================================== --检查测试表是否存在 IF(O ...

  5. 曲演杂坛--使用ALTER TABLE修改字段类型的吐血教训

    --===================================================================== 事件起因:开发发现有表插入数据失败,查看后发现INT类型 ...

  6. 曲演杂坛--蛋疼的ROW_NUMBER函数

    使用ROW_NUMBER来分页几乎是家喻户晓的东东了,而且这东西简单易用,简直就是程序员居家必备之杀器,然而ROW_NUMBER也不是一招吃遍天下鲜的无敌BUG般存在,最近就遇到几个小问题,拿出来供大 ...

  7. 曲演杂坛--当ROW_NUMBER遇到TOP

    值班期间研发同事打来电话,说应用有超时,上服务器上检查发现有SQL大批量地执行,该SQL消耗IO资源较多,导致服务器存在IO瓶颈,细看SQL,发现自己都被整蒙了,不知道这SQL是要干啥,处理完问题赶紧 ...

  8. 曲演杂坛--特殊字符/生僻字与varchar

    对于中文版的SQL SERVER,默认安装后使用的默认排序规则为Chinese_PRC_CI_AS,在此排序规则下,使用varchar类型来可以“正常存取”存放中文字符以及一些东南亚国家的字符,同时v ...

  9. 曲演杂坛--EXISTS语句

    通常在我写EXISTS语句时,我会写成IF EXISTS(SELECT TOP(1) 1 FROM XXX),也没细细考究过为什么要这么写,只是隐约认为这样写没有啥问题,那今天就深究下吧! 首先准备测 ...

随机推荐

  1. 手机屏幕左下角显示Fastboot mode是什么情况?

    刚给老婆买了一个多月的魅蓝NOTE,几天前开不了机,黑屏但左下角显示:Fastboot mode…….无论按电源键还是电源键加音量加键进行重置都没有任何作用,关后自己会重启黑屏左下角显示Fastboo ...

  2. 【校招面试 之 C/C++】第16题 C++ new和delete的实现原理

    1.new new操作针对数据类型的处理,分为两种情况: (1)简单数据类型(包括基本数据类型和不需要构造函数的类型) 代码实例: int* p = new int; 汇编码如下: int* p = ...

  3. repeater嵌套RadioButtonList赋值

    <asp:Repeater ID="Repeater1" runat="server"         onitemdatabound="Rep ...

  4. instanceof用法及本质:

    import static java.lang.System.*; public class InstanceofTest{ public static void main(String[] args ...

  5. html 5 如何限制上传的文件类型 (uploadifive)

    可以直接设置input标签的accept属性来限制上传文件的类型 <input type="file" accept="application/msword&quo ...

  6. mysql 导入导出摘要

    1.导入by数据文件. mysql>load data infile '文件路径' into table 表名 fields terminated by '字段分隔符' lines termin ...

  7. 2018.06.29 NOIP模拟 边的处理(分治+dp)

    边的处理(side.cpp) [问题描述] 有一个 n 个点的无向图,给出 m 条边,每条边的信息形如<x,y,c,r><x,y,c,r><x,y,c,r>. 给出 ...

  8. 2018.08.16 POJ1183反正切函数的应用(简单数学)

    传送门 代数变形一波. 显然有b,c>a. 那么这样的话可以令b=a+m,c=a+n. 又有a=(bc-1)/(b+c). 带入展开可知m*n=a*a+1. 要让m+n最小只需让m最大,这个结论 ...

  9. Nginx安装SSL安全证书

    1. 在Nginx的安装目录下的config目录下创建cert目录,并且将下载的证书全部文件拷贝到cert目录中.如果申请证书时是自己创建的CSR文件,请将对应的私钥文件放到cert目录下并且命名为2 ...

  10. Part 5 - Django ORM(17-20)

    https://github.com/sibtc/django-beginners-guide/tree/v0.5-lw from django.conf.urls import url from d ...