非NULL场景下多段T-SQL UPDATE语句与合并语句、JOIN语法UPDATE的等效性问询
T-SQL UPDATE 语句等效性验证
先把你提到的几个SQL语句整理出来,再逐一分析它们的等效性:
原始两个独立UPDATE语句
-- Query #1 UPDATE #R12 SET SOURCE_NAME = DEFLT.SOURCE_NAME FROM R12_MLR_REBATE_GL_STRING_DEFLT DEFLT WHERE #R12.PAYMT_TY = DEFLT.PAYMT_TY AND #R12.AMOUNT_TYPE = DEFLT.AMOUNT_TYPE AND #R12.COMPANY <> @BNKER_COMPANY AND DEFLT.BNKER_IND = 'N'
-- Query #2 UPDATE #R12 SET SOURCE_NAME = DEFLT.SOURCE_NAME FROM R12_MLR_REBATE_GL_STRING_DEFLT DEFLT WHERE #R12.PAYMT_TY = DEFLT.PAYMT_TY AND #R12.AMOUNT_TYPE = DEFLT.AMOUNT_TYPE AND #R12.COMPANY = @BNKER_COMPANY AND DEFLT.BNKER_IND = 'Y'
合并后的UPDATE语句
UPDATE #R12 SET SOURCE_NAME = DEFLT.SOURCE_NAME FROM R12_MLR_REBATE_GL_STRING_DEFLT DEFLT WHERE #R12.PAYMT_TY = DEFLT.PAYMT_TY AND #R12.AMOUNT_TYPE = DEFLT.AMOUNT_TYPE AND ((#R12.COMPANY <> @BNKER_COMPANY AND DEFLT.BNKER_IND = 'N') OR (#R12.COMPANY = @BNKER_COMPANY AND DEFLT.BNKER_IND = 'Y') )
JOIN写法的UPDATE语句
UPDATE R12 SET SOURCE_NAME = DEFLT.SOURCE_NAME FROM #R12 R12 INNER JOIN R12_MLR_REBATE_GL_STRING_DEFLT DEFLT ON R12.PAYMT_TY = DEFLT.PAYMT_TY AND R12.AMOUNT_TYPE = DEFLT.AMOUNT_TYPE AND ((R12.COMPANY <> @BNKER_COMPANY AND DEFLT.BNKER_IND = 'N') OR (R12.COMPANY = @BNKER_COMPANY AND DEFLT.BNKER_IND = 'Y'))
1. 依次执行Query #1 + Query #2 VS 合并后的单条UPDATE
这两种方式100%等效,核心原因是两个原始Query的筛选条件是完全互斥的:
- Query #1只处理
#R12.COMPANY <> @BNKER_COMPANY的行,Query #2只处理#R12.COMPANY = @BNKER_COMPANY的行。由于你明确说明场景不允许NULL值,所以不存在任何一行会同时满足两个Query的WHERE条件,也就不会有行被重复更新。 - 合并后的语句用
OR把两个互斥条件组合,本质上是把两次独立的更新合并成一次批量操作,筛选出的目标行范围、每个行匹配的DEFLT数据源完全一致,最终SOURCE_NAME的赋值结果和分两次执行没有任何区别。
2. JOIN写法的UPDATE VS 前两种方式
这种显式JOIN的写法结果也完全一致,理由如下:
- 在T-SQL中,
UPDATE ... FROM [表A], [表B] WHERE [连接/过滤条件]的隐式连接写法,和UPDATE ... FROM [表A] INNER JOIN [表B] ON [连接/过滤条件]的显式JOIN写法,在逻辑上是等价的。你把原本的连接条件(PAYMT_TY和AMOUNT_TYPE匹配)加上业务过滤条件(公司与BNKER_IND的组合)放到ON子句里,和把这些条件放到WHERE子句的隐式连接,最终筛选出的#R12与DEFLT的匹配对完全相同。 - 同样基于条件的互斥性,不会出现一行
#R12匹配到多行DEFLT的情况(即使DEFLT表有重复数据,你的条件也会确保每个#R12行只匹配到符合BNKER_IND要求的那一行),所以SOURCE_NAME的赋值结果不会有差异。
额外风险提示
如果未来业务规则变化,比如DEFLT表中同一PAYMT_TY+AMOUNT_TYPE下同时存在BNKER_IND='Y'和BNKER_IND='N'的行,或者#R12的COMPANY字段允许NULL值,可能会出现一行#R12匹配到多行DEFLT的情况。此时T-SQL会随机选择其中一行的SOURCE_NAME进行赋值,这种情况下三种写法的结果可能会出现不一致,但基于你当前的约束(不允许NULL),这种风险暂时不存在。
内容的提问来源于stack exchange,提问作者Chad
相关产品推荐
相关产品推荐

