lightdb union_null规则及解决方案

发布时间 2023-10-24 19:49:47作者: 小小罗的背影

在pg/lightdb中,当使用union对两个表进行关联时,可能会因为字段的类型不匹配导致报错:

 

 

ERROR:  UNION types integer and text cannot be matched

但并非所有union … null情况均不支持。在pg/lightdb中,针对存在多个union情况,

1. lighdb union类型匹配逻辑如下图所示:

 

 

首先$1与$2进行类型匹配确定最终类型,然后再与$3进行类型匹配确定类型,然后再与$4类型匹配确定类型,以此类推;

2. 在lightdb中,null为unknown类型,默认隐式转换第一位为text文本类型;

3. 当有distinct等修饰null时,会直接确定类型为text,如 select distinct null这里的distinct null即确定为text类型;

4. union语句中报类型不匹配错误仅针对大类型之间不匹配而报错,如整型和字符串类型不匹配,大类型内部union之间是支持的(会进行隐式转换),如int4、int8,在union两边是可以正常执行的。

                    

支持

 1、select null union select 1;

  select 1 union select null;

  以上场景均支持。因为null首先为unknown类型,在进行union时,会将两边类型进行自动匹配,这里null均隐式转换为了整型。

 

 2、select 1 union select null union null;    *注:这里的1和第一个null结合确定为整型

  select null union select 1 union null;    *注:这里的第一个null和1结合确定为整型

  select null union select null union null;      *注:这里前两null结合确定为text文本类型

  以上场景均支持。因为前两者类型确定后,第三个unknown类型的null即与确定的类型进行匹配,而不会报错。

不支持

       改写方案为将null as col_name 改为cast(null as 数据类型) as col_name

       具体如下:

  1、select null union select null union select 1;

  前两个null均为unknown,两个unknown类型进行匹配后确定类型为text,导致与第三个语句中的整型1不匹配报错。

  改写方案:select cast(null as int) union select cast(null as int) union select 1;

  或者调换顺序:select null union select 1 union select null;    *注:这里第一个null和1结合首先确定为整型

 

  2、select distinct 1 union select distinct null;

  select distinct null union select distinct 1;

  在null前面有distinct进行修饰时,会直接将null确定为text类型,导致不管null位置在哪里,均会报与整型不匹配错误。

  改写方案:select distinct cast (null as int) union select distinct 1;

                   select distinct 1 union select distinct cast(null as int);

 

     注意

  1. 不管表中有无数据,当出现union两边大类型不匹配时,在lightdb中执行sql均会报错,故改写前可先将sql在lightdb中执行,如报union类型不匹配错误时再进行修改,修改后在lighdb和oracle库中均需执行确认无问题;
  2. null具体修改为cast(null as 数据类型),该数据类型需和与之union匹配的字段类型保持一致,例如:

    select distinct 1::smallint union select distinct 1::bigint union select distinct 1::number union select distinct null;

    报错:

    ERROR:  UNION types numeric and text cannot be matched

    LINE 1: ... union select distinct 1::number union select distinct null;

 

    其实也可以根据报错信息来确定实际要改为何种类型(注:number与numeric类型在lightdb中为同一种)

    修改为:

         select distinct 1::smallint union select distinct 1::bigint union select distinct 1::number union select distinct cast(null as number);