Oracle MAX(char(1))union with null在记录变量中扩展到32767字节

bis0qfac  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(74)

有没有人经历过这种情况,或者知道这是一个错误还是一个“功能”?我的CHAR(1)值被空格吹到了最大PL/SQL字符串长度(32767),这当然会破坏下游的东西,只需要1个字符。
简单测试:

BEGIN
  FOR rec_data IN (SELECT MAX('Y') bind_all_ips
                     FROM dual
                  UNION ALL
                  SELECT NULL bind_all_ips                        
                    FROM dual) 
  LOOP
     dbms_output.put_line('bind_all_ips length = '||LENGTH(rec_data.bind_all_ips));
  END LOOP;
END;

输出量:

bind_all_ips length = 32767

同样的事情也发生在一张table上:

create table tab1 (bind_all_ips char(1));
insert into tab1 values ('Y');
commit;

BEGIN
  FOR rec_data IN (SELECT MAX(bind_all_ips) bind_all_ips
                     FROM tab1
                  UNION ALL
                  SELECT NULL bind_all_ips                        
                    FROM dual) 
  LOOP
     dbms_output.put_line('bind_all_ips length = '||LENGTH(rec_data.bind_all_ips));
  END LOOP;
END;

输出量:

bind_all_ips length = 32767

只有在以下情况下才会发生:
1.使用CHAR数据类型,
1.它被选择并与MAX()MIN()聚合
1.然后用另一个为同一列指定文本NULL的块对该查询执行UNION
1.结果通过PL/SQL中的隐式游标获取
当然可以通过显式地将其转换为varchar2来解决,但这一定是一个bug,对吗?

更新:

此行为发生在所有版本上,包括8.1.7(可能更早),从9.2.0.6到12.1.0.2,它导致4000字节。
在9.2.0.3到9.2.0.5之间,它不会发生(它返回1个字节)。
在12.2.0.1到19.20之间(可能更晚,我不能测试任何东西),它的结果是32767字节。

yshpjwxd

yshpjwxd1#

您可以使用CAST(MAX('Y') AS CHAR(1))绕过它

BEGIN
  FOR rec_data IN (
    SELECT CAST(MAX('Y') AS CHAR(1)) AS bind_all_ips
    FROM   dual
  UNION ALL
    SELECT NULL
    FROM   dual
  ) 
  LOOP
    dbms_output.put_line('bind_all_ips length = '||LENGTH(rec_data.bind_all_ips));
  END LOOP;
END;
/

相关问题