SnailOnModem  发表于 2021-6-17 15:27 显示全部楼层 楼主
与GP对照,感觉GBase8a的exists貌似有Bug。

1. GP版本
GP服务端:V5.19.0
psql客户端:V8.3.23

2. GBase版本
GBase服务端:version 8.6.2.43-R31.126790
GBase客户端:ver 8.6.2.43-R18.116553, for suse-linux-gnu (x86_64) using readline 6.3

3. 测试用的Shell程序内容

# 测试update+子查询功能

echo "----- GP数据库 -----"

# 说明:
# 支持, 可以执行, exists查询得到时返回true, 查询不到时返回false, 不会返回null。

psql <<!

\! echo "创建表 ..."
create temporary table TempCode         -- 代码表
(
Code    varchar(10)     -- 代码
,Name   varchar(20)     -- 名称
)
on commit preserve rows
distributed by
(
Code                    -- 代码
)
;
create temporary table TempExist        -- 存在状态表
(
ExistA  boolean         -- 代码CodeA是否存在
,ExistB boolean         -- 代码CodeB是否存在
)
on commit preserve rows
distributed by
(
ExistA                  -- 代码CodeA是否存在
)
;

\! echo "插入代码数据 ..."
insert into TempCode
values
(
'CodeA'
,'NameA'
)
;

\! echo "插入存在状态初始数据 ..."
insert into TempExist
values
(
false
,false
)
;

\! echo "查询存在状态数据 ..."
select  *
from    TempExist
;

\! echo "修改存在状态数据 ..."
update  TempExist
set
        ExistA =
                exists
                (
                        select  1
                        from    TempCode        -- 代码表
                        where   Code = 'CodeA'          -- 查询得到
                )
        ,
        ExistB =
                exists
                (
                        select  1
                        from    TempCode        -- 代码表
                        where   Code = 'CodeB'          -- 查询不到
                )

;

\! echo "修改后查询存在状态数据 ..."
select  *
from    TempExist
;

\! echo "删除表 ..."
drop table TempCode
;
drop table TempExist
;

!


echo "----- GBase数据库 -----"

# 说明:
# 语法支持, 可以执行, exists查询得到时返回true, 查询不到时没有返回false, 而是返回null
# 推测:
# 查询不到时, exists应该返回false, 却返回了null。这可能是GBase的一个Bug。

stdbuf -o0 gccli <<!

\! echo "选择数据库 ..."
use gbase
;

\! echo "创建表 ..."
create temporary table TempCode         -- 代码表
(
Code    varchar(10)     -- 代码
,Name   varchar(20)     -- 名称
)
distributed by
(
'Code'                  -- 代码
)
;
create temporary table TempExist        -- 存在状态表
(
ExistA  bool            -- 代码CodeA是否存在
,ExistB bool            -- 代码CodeB是否存在
)
replicated              -- 分布键只允许varchar和int类型, 所以使用复制表
;

\! echo "插入代码数据 ..."
insert into TempCode
values
(
'CodeA'
,'NameA'
)
;

\! echo "插入存在状态初始数据 ..."
insert into TempExist
values
(
false
,false
)
;


\! echo "查询存在状态数据 ..."
select  *
from    TempExist
;

\! echo "修改存在状态数据 ..."
update  TempExist
set
        ExistA =
                exists
                (
                        select  1
                        from    TempCode        -- 代码表
                        where   Code = 'CodeA'  -- 查询得到
                )
        ,
        ExistB =
                exists
                (
                        select  1
                        from    TempCode        -- 代码表
                        where   Code = 'CodeB'  -- 查询不到
                )
;

\! echo "修改后查询存在状态数据 ..."
select  *
from    TempExist
;

\! echo "删除表 ..."
drop table TempCode
;
drop table TempExist
;

!


4. 执行程序的输出结果

----- GP数据库 -----
创建表 ...
CREATE TABLE
CREATE TABLE
插入代码数据 ...
INSERT 0 1
插入存在状态初始数据 ...
INSERT 0 1
查询存在状态数据 ...
exista | existb
--------+--------
f      | f
(1 row)
修改存在状态数据 ...
UPDATE 1
修改后查询存在状态数据 ...
exista | existb
--------+--------
t      | f
(1 row)
删除表 ...
DROP TABLE
DROP TABLE
----- GBase数据库 -----
选择数据库 ...
创建表 ...
插入代码数据 ...
插入存在状态初始数据 ...
查询存在状态数据 ...
ExistA  ExistB
0       0
修改存在状态数据 ...
修改后查询存在状态数据 ...
ExistA  ExistB
1       NULL
删除表 ...


6. 貌似问题

GBase,修改后,ExistB为null,而不是false(0)。

麻烦研发团队核实分析一下?谢谢!

java2000  发表于 2021-6-21 09:43 显示全部楼层 沙发
感谢反馈。
测试了一下,对空结果集的处理怀疑有问题,建议用if做一下判断。
if(exists (), 1,0)
一个三元函数,第一个是判断条件,第二个是符合的值,第三个是不符合的值。


UPDATE TempExist
SET ExistA =

IF (
    EXISTS (
      SELECT 1
      FROM TempCode -- 代码
      WHERE Code = 'CodeA' -- 查询得到
      )
    ,1
    ,0
    )
  ,ExistB =
  IF (
      EXISTS (
        SELECT 1
        FROM TempCode -- 代码
        WHERE Code = 'CodeB' -- 查询不到
        )
      ,1
      ,0
      );
您需要登录后才可以回帖 登录 | 立即注册