如何通过cx_Oracle模块正确调用fnd_concurrent.wait_for_request存储函数
问题原因与解决方案
问题根源
- 输出VARCHAR2参数未指定足够长度:调用
cursor.var(str)时cx_Oracle默认仅分配极短的字符长度(通常为1字符),而fnd_concurrent.wait_for_request的输出参数(尤其是message字段)返回内容长度远大于默认值,就会触发ORA-06502: PL/SQL: numeric or value error报错。 - 部分cx_Oracle版本对PL/SQL原生BOOLEAN类型的返回值存在兼容问题,也可能触发类型不匹配的同类报错。
解决方案
方案1:调整输出参数长度(优先尝试)
给所有VARCHAR2类型的输出参数指定足够的存储长度即可解决绝大多数场景的报错:
# 按输出内容长度合理分配存储空间,message字段可设置更长 lc_phase = cursor.var(str, 100) lc_status = cursor.var(str, 100) lc_dev_phase = cursor.var(str, 100) lc_dev_status = cursor.var(str, 100) lc_message = cursor.var(str, 4000) bool_result = cursor.callfunc('fnd_concurrent.wait_for_request', bool, [123456789,5,15,lc_phase,lc_status,lc_dev_phase,lc_dev_status,lc_message]) print('fnd_concurrent.wait_for_request result: ', bool_result)
方案2:使用匿名PL/SQL块调用(兼容性最高)
如果调整长度后仍有报错,可通过匿名PL/SQL块将BOOLEAN类型的返回值转换为数值类型,避开cx_Oracle对PL/SQL BOOLEAN的兼容问题:
# 声明所有变量 result_num = cursor.var(int) lc_phase = cursor.var(str, 100) lc_status = cursor.var(str, 100) lc_dev_phase = cursor.var(str, 100) lc_dev_status = cursor.var(str, 100) lc_message = cursor.var(str, 4000) # 执行匿名PL/SQL块完成调用和类型转换 cursor.execute(""" DECLARE l_result BOOLEAN; BEGIN l_result := fnd_concurrent.wait_for_request( request_id => :req_id, interval => :interval, max_wait => :max_wait, phase => :phase, status => :status, dev_phase => :dev_phase, dev_status => :dev_status, message => :message ); :result_num := CASE WHEN l_result THEN 1 WHEN NOT l_result THEN 0 ELSE NULL END; END; """, { 'req_id': 123456789, 'interval': 5, 'max_wait': 15, 'phase': lc_phase, 'status': lc_status, 'dev_phase': lc_dev_phase, 'dev_status': lc_dev_status, 'message': lc_message, 'result_num': result_num }) # 转换得到布尔类型结果 bool_result = bool(result_num.getvalue()) if result_num.getvalue() is not None else None print('fnd_concurrent.wait_for_request result: ', bool_result)
内容的提问来源于stack exchange,提问作者alaptiko
相关产品推荐
相关产品推荐

