Merge语句中NULL的陷阱
NULL表示unknown,不确定值,所以任何值(包括null值)和NULL值比较都是不可知的,在on子句,where子句,Merge或case的when子句中,任何值和null比较的结果都是false,这就是NULL设下的陷阱,我被坑过。
有一次,我使用Merge同步数据,由于target表中存在null值,虽然在source表中对null值做过处理,但是忽略了target表中的null值,导致数据merge失败。
step1,创建示例数据
--create source table
create table dbo.dt_source
(
id int null,
code int null
)
on [primary]
with(data_compression=page) --create target table
create table dbo.dt_target
(
id int null,
code int null
)
on [primary]
with(data_compression=page)
step2,插入示例数据
示例数据中,Source表和Target表中都存在null值,不管是在Source表,还是在Target表,都要避免和null值进行比较。
--insert data into table
insert into dbo.dt_source(id,code)
values(1,1),(2,2),(3,null) insert into dbo.dt_target(id,code)
values(1,1),(2,null)
step3,错误写法:只处理Source表中的null,而忽略Target表中的null
-- -1 stand for unknwon value
merge dbo.dt_target t
using dbo.dt_source s
on t.id=s.id
when matched and( t.code<>isnull(s.code,-1))
then update
set t.code=s.code
when not matched
then insert(id,code)
values(s.id,s.code);
查看Target和Srouce表中的数据,数据不同步,不同步的原因是when matched子句之后的and 条件, t.code中存在null值,null值和任何值(包括null值)比较的结果都是unknown,在when子句中视为false。

正确写法1,不管是在target表,还是在source表,只要存在null值,必须进行处理,避免出现和null进行比较的情况。
处理的方式是使用一个值来表示unknwon,如果ID列有效值不可能是负值,那么可以使用-1来代替unknown。因为-1和-1 是相等的,逻辑上就将null值和null值视为相同。
-- -1 stand for unknwon value
merge dbo.dt_target t
using dbo.dt_source s
on t.id=s.id
when matched and( isnull(t.code,-1)<>isnull(s.code,-1))
then update
set t.code=s.code
when not matched
then insert(id,code)
values(s.id,s.code);
正确写法2,在条件子句中,使用is null或 is not null来处理null值。
Tsql 使用is null和is not null来确实是,不是 null。 null is null 的逻辑值是true,other_value is null 为false, other_value is not null 为true。
merge dbo.dt_target t
using dbo.dt_source s
on t.id=s.id
when matched and( t.code<>s.code or t.code is null or s.code is null)
then update
set t.code=s.code
when not matched
then insert(id,code)
values(s.id,s.code);
Merge语句中NULL的陷阱的更多相关文章
- SQL语句中=null和is null
平时经常会遇到这两种写法:IS NOT NULL与!=NULL.也经常会遇到数据库有符合条件!=NULL的数据,但是返回为空集合.实际上,是由于对二者使用区别理解不透彻. 默认情况下,推荐使用 IS ...
- Sql server的Merge语句,源表中如果有重复数据会导致执行报错
用过sql server的Merge语句的开发人员都应该很清楚Merge用来做表数据的插入/更新是非常方便的,但是其中有一个问题值得关注,那就是Merge语句中的源表中不能出现重复的数据,我们举例来说 ...
- 【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句
原文:[SQL Server学习笔记]Delete 语句.Output 子句.Merge语句 DELETE语句 --建表 select * into distribution from sys.obj ...
- 【转载】SQL Server - 使用 Merge 语句实现表数据之间的对比同步
原文地址:SQL Server - 使用 Merge 语句实现表数据之间的对比同步 表数据之间的同步有很多种实现方式,比如删除然后重新 INSERT,或者写一些其它的分支条件判断再加以 INSERT ...
- 转:SQL Server - 使用 Merge 语句实现表数据之间的对比同步
表数据之间的同步有很多种实现方式,比如删除然后重新 INSERT,或者写一些其它的分支条件判断再加以 INSERT 或者 UPDATE 等.包括在 SSIS Package 中也可以通过 Lookup ...
- SQL Server - 使用 Merge 语句实现表数据之间的对比同步
表数据之间的同步有很多种实现方式,比如删除然后重新 INSERT,或者写一些其它的分支条件判断再加以 INSERT 或者 UPDATE 等.包括在 SSIS Package 中也可以通过 Lookup ...
- 如何理解T-SQL中Merge语句(二)
写在前面的话:上一篇写了如何理解T-SQL中Merge语句,基本把Merge语句要讲的给讲了,在文章的后面,抛出了几个结,当时没有想明白怎么去用文字表达,这一篇就来解答一下这几个结,又是一篇“天马行空 ...
- SQLServer 2008中SQL增强之三 Merge(在一条语句中使用
SQLServer 2008中SQL增强之三 Merge(在一条语句中使用Insert,Update,Delete) SQL Server 2008提供了一个增强的SQL命令Merge,用法参看M ...
- 如何理解T-SQL中Merge语句
写在前面的话:之前看过Merge语句,感觉没什么用,完全可以用其他的方式来替代,最近又看了看Merge语句,确实挺好用,可以少写很多代码,看起来也很紧凑,当然也有别的优点. ====正文开始===== ...
随机推荐
- [翻译] VENCalculatorInputView
VENCalculatorInputView https://github.com/venmo/VENCalculatorInputView VENCalculatorInputView is the ...
- java中判断对象中属性值是否为空的函数
public boolean checkObjFieldIsNull(Object obj) throws IllegalAccessException { boolean flag = false; ...
- nodejs API(一)
不要注重版本 URL 官网所在位置:https://nodejs.org/dist/latest-v8.x/docs/api/url.html URL网址解析的好帮手: url有三个可调用的方法:ur ...
- 利用Intellij IDEA开发Spark程序
网上例子大多是基于scala的,并且配置基于sbt.scala的eclipse环境超级麻烦,所以下载IDEA. 准备:jdk,IDEA安装(可以不用事先安装sbt和Scala,这在IDEA里都可以pl ...
- 在CentOS7上部署 Kubernetes集群
yum -y install etcd docker flannel kubenetes 一般会遇到没有k8s源的问题,先 yum update -y 看是否有效,如果还是没用就创建yum 源,再 ...
- Python3的动态加载模块简单实例
import os import sys import time import myconfig b = ['123'] a = os.path.abspath(myconfig.__file__) ...
- CentOS中配置VNC Server
环境:CentOS 6.4 1.安装tigervnc-server及相关软件 首先检查系统中是否安装tigervnc-server安装包 rpm -qa tigervnc-server 如果没有就直接 ...
- HDU 1114(没有变形的完全背包)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1114 Piggy-Bank Time Limit: 2000/1000 MS (Java/Others ...
- linux文件系统初始化过程(1)---概述
术语表: struct task:进程 struct mnt_namespace:命名空间 struct mount:挂载点 struct vfsmount:挂载项 struct file:文件 st ...
- 存储过程定义多个游标多个begin
1.直接定义多个显示游标 CREATE OR REPLACE PROCEDURE ACC.DBP_REALCITYTRAFFICCNT IS CURSOR cur1 IS SELECT ... --第 ...