PG迁移必读(五):重新认识NULL
Barry Chen

PG中的NULL是不能用于比较的,也不能用于运算操作等。

SELECT NULL != 'abc'; – 这个返回NULL

SELECT NULL = 'abc' ; – 同样返回NULL

SELECT NULL = NULL; – 还是返回NULL

注意,这里返回的是NULL,不是true/false。这说明PG的NULL是不能用于比较的。

再看一段PG与Sybase的NULL使用对比。

 

 

 

 

 

 

下面介绍两个在我们CP8项目中遇到过的由NULL引起的issues。

 

案例一. NULL导致AWS SCT没有正确转换Sybase代码

 

下面原Sybase代码,其功能就是当v为null时,返回value1,否则,返回value2
case v when null then value1 else value2 end 

AWS SCT转换后的PG代码:

CASE v WHEN NULL THEN value1 ELSE value2 END  

可以看出,除了大小写不同外,其它没有变化。但这代码在PG中运行是有问题的,不管v是否为NULL,都会返回value2。

正确的做法是使用IS NULL子句,因此PG正确的代码应该是:
CASE WHEN v is NULL THEN value1 ELSE value2 END

(本案例由Wick发现并解决)

所以,在PG中,可以使用IS NULL和IS NOT NULL来显式地检查NULL值,但不能直接使用比较运算符(=,!=)进行性判断。

 

案例二. NULL导致用字符串连接失败

看下面的SQL,功能是将两个字符串连接起来,其中var1和var2是varchar变量:

var2 := 'value=' || var1;

当var1非NULL时,这个代码是能正常运行的;但当var1为NULL时,这行代码就崩溃了,var2 被赋值为NULL。这是因为PG认为NULL不能参与运算操作。在PG中,正确的赋值方法是使用concat函数:

  var2 := concat('value=', var1);  -- 这个返回 “value=”,

或使用coalesce函数

  var2 :=  'value=' || coalesce(var1, 'NULL');  -- 这个返回 ”value=NULL“

重新认识PG中NULL,可以帮助我们编写正确的SQL代码。