Sailfish环境下DB2/ZOS无数据时执行ROW_NUMBER()查询报DECFLOAT错误
Sailfish部署环境DB2空结果触发DECFLOAT驱动异常问题
触发场景特征
- 异常仅在Sailfish部署节点对接的IBM DB2 ZOS库上复现,同一段SQL在其他部署环境、本地开发库执行无报错
- 触发条件固定为查询无匹配返回数据的场景,只要WHERE条件能匹配到实际数据,语句执行完全正常
- 语句涉及的所有投影列、分区列、排序列均为整数类型,逐行排查不存在显式的字符转数值转换逻辑
复现SQL
SELECT jersey_number, team_nm, ROW_NUMBER () OVER ( PARTITION BY Model_Football.member_idn, Model_Football.Arm_Power_Idn, Model_Football.Speed_Idn ORDER BY Model_Football.member_idn, Model_Football.Arm_Power_Idn, Model_Football.Speed_Idn) AS Dual_threat_id FROM QB_SCHOOL WHERE pos = 'QB'
抛出的驱动错误
[IBM][DB2/LINUXPPC64LE] Invalid character found in a character string argument of the function "DECFLOAT".
问题根因
这个报错和SQL语法、表内字段类型没有实质关联,本质是驱动和ZOS库版本的兼容问题:
- DB2的客户端驱动在解析窗口函数返回值的元数据时,会默认对无显式类型声明的ROW_NUMBER()结果做DECFLOAT类型的预判
- 当查询结果为空时,ZOS实例返回的结果集元数据中,窗口函数对应的字段类型标识存在字段长度截断,驱动解析到截断的非数字标识字符串时,会错误将这段字符串传入DECFLOAT转换函数,最终抛出非法字符的报错
- Sailfish部署环境默认内置的DB2 Linux PPC64LE驱动版本较旧,没有适配ZOS库空结果场景下的元数据返回格式;其他环境使用的驱动版本更高,已经覆盖了这个解析逻辑的兼容问题,因此不会触发同类异常
这个问题不需要调整业务过滤条件或者表结构,因为异常完全发生在驱动的结果集解析层,有匹配数据返回时的查询逻辑不受任何影响
可用解决方式
- 前置加结果存在性判断:在执行带窗口函数的查询前,先执行一次同过滤条件的
COUNT(*)查询,确认有匹配数据后再执行主查询,直接绕过驱动对空结果集的元数据解析流程 - 升级Sailfish环境内置的DB2驱动到11.5.7及以上版本,该版本已修复ZOS空结果集元数据的解析逻辑,不会再错误触发DECFLOAT转换流程
- 给窗口函数的返回值加显式类型转换,绕过驱动对无类型声明窗口值的默认DECFLOAT预判逻辑,改写示例:
CAST(ROW_NUMBER () OVER ( PARTITION BY Model_Football.member_idn, Model_Football.Arm_Power_Idn, Model_Football.Speed_Idn ORDER BY Model_Football.member_idn, Model_Football.Arm_Power_Idn, Model_Football.Speed_Idn ) AS INTEGER) AS Dual_threat_id
内容的提问来源于stack exchange,提问作者Christopher Fowler
相关产品推荐
相关产品推荐

