最近工作中发现某应用执行操作报错“字符串截断”,找到对应sql语句后发现问题出在cast强制转换这里,经过简化重现,其报错sql的本质如下:

select cast(to_number(123) as varchar2(1)) p6 from dual;

可以看出当要把数据类型为number的数字强制转换成小于其自身长度的字符串类型时才会报错。找到出问题的本质其实就很好规避这个报错了,下面就这个问题讨论一下不同数据类型下的cast会有什么不同的表现吗?这里我们主要讨论不同数据类型下转换成小于其本身长度的varchar2类型。
1.number类型cast成长度更短的 varchar2
select cast(to_number(123) as varchar2(1)) p6 from dual; 

这种场景下的“字符串截断”报错可以引申到numeric,dec,number,float,double等类型上。
2.int类型cast成长度更短的 varchar2
select cast(123 as varchar2(1)) p6 from dual;

可以看到int类型与上述的number类型报错表现是不同的,报错提示“数据转换丢失警告”,这种报错可以引申到bigint,tinyint,smallint等整数类型上。
3.varhcar2类型cast成长度更短的varhcar2
select ‘123’,cast(‘123’ as varchar2(1)) p6 from dual; 

可以看到varchar2类型cast成长度更短的varchar2类型可以执行成功,相当于自动做了字符串截断,效果等同于left(123,1)。同样的,char类型的表现与varchar2是相同的,也可以执行成功,在此不再赘述。

下面看看oracle的表现如何:

可以看到,oracle对于number和int类型强制转换为长度小于数据本身的varchar2时报错是相同的,而对于varchar2类型则与达梦表现一样,能够成功执行,相当于自动做了字符串的截断。
根据上述介绍我们应该知道当出现“字符串截断”报错时,可能发生的场景如下:
1.要修改或插入的字符串数据长度超过表中字段定义长度,这种情况很好判断,使用lengthb函数计算一下字符串占用字节数是否大于定义长度即可;
2.数据类型为number(不限于)的数字强制转换成小于其自身长度的定长/变长字符串类型,如上述讨论的第一种情况,遇到这种情况就该好好考虑一下sql做cast强制转换是否合理了。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐