Jira ScriptRunner中DatabaseUtil.withSql调用Oracle存储过程报错ORA-01403
针对你在Jira ScriptRunner v9.15.2中调用Oracle存储过程遇到的ORA-01403错误,结合你的场景(本地IntelliJ正常、ScriptRunner查询正常但存储过程报错),以下是几个核心问题根源和对应解决方法:
1. ScriptRunner中存储过程调用语法不符合JDBC规范
本地IntelliJ可能用了Oracle专属API或宽松的调用逻辑,但ScriptRunner的DatabaseUtil.withSql基于Groovy Sql类,对Oracle存储过程的调用语法(尤其是OUT参数处理)有严格要求。如果参数绑定或调用语句格式错误,哪怕存储过程名称写错,都会触发ORA-01403这类混淆性错误。
解决步骤
使用标准JDBC CallableStatement语法调用,确保正确注册OUT参数,示例代码:
import groovy.sql.Sql def result = DatabaseUtil.withSql("oracle") { sql -> // 存储过程调用语句,参数位置不能省略(可选参数传null让Oracle用默认值) def callStmt = "{ call YOUR_PROC_NAME(?, ?, ?) }" def stmt = sql.connection.prepareCall(callStmt) // 绑定IN参数,可选参数不传则设为null stmt.setString(1, optionalParam1 ?: null) stmt.setString(2, optionalParam2 ?: null) // 注册OUT参数,类型必须和存储过程定义严格匹配(比如VARCHAR2对应Types.VARCHAR) stmt.registerOutParameter(3, java.sql.Types.VARCHAR) stmt.execute() // 获取OUT参数结果 def outVal = stmt.getString(3) log.info("存储过程返回值:${outVal}") return "Process Successful" }
注意:不能跳过可选参数的位置,哪怕Oracle定义了默认值,必须显式传递null让Oracle触发默认值逻辑。
2. ScriptRunner连接池的会话上下文与本地不一致
ScriptRunner连接池使用的数据库账号可能和本地测试的账号权限、默认Schema不同,或者会话参数(如NLS格式、当前Schema)不匹配,导致存储过程执行时找不到目标数据。
解决步骤
- 检查连接池账号权限:确保该账号有执行目标存储过程的权限,以及存储过程涉及表的读写权限。
- 显式指定Schema:调用存储过程时加上Schema前缀,比如
SCHEMA_NAME.YOUR_PROC_NAME,避免默认Schema不一致的问题。 - 对比会话信息:在ScriptRunner中执行查询
SELECT USER, SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') FROM DUAL;,和本地IntelliJ的执行结果对比,确认账号和Schema一致。
3. Groovy/JDBC版本兼容性问题
ScriptRunner内置的Groovy版本或Oracle JDBC驱动版本可能和本地IntelliJ使用的不一致,导致参数绑定或存储过程调用的兼容性问题,比如旧版本驱动对OUT参数的处理逻辑不同。
解决步骤
- 确认JDBC驱动版本:Jira 9.15.2默认的Oracle驱动可能较旧,可在ScriptRunner的Resources中更新匹配Oracle数据库版本的驱动包。
- 严格使用标准JDBC语法:避免使用Oracle专属的扩展API,减少版本差异带来的问题。
4. 存储过程内部异常被掩盖
ORA-01403可能是存储过程内部的SELECT语句未找到数据,但存储过程未处理该异常,导致抛出到上层。而本地执行正常可能是因为本地传入的参数能匹配到数据,ScriptRunner中参数传递存在差异。
解决步骤
- 存储过程加日志:在存储过程内部添加日志逻辑,将传入的参数、执行的SQL写入Oracle日志表,对比本地和ScriptRunner的参数差异。
- 脚本打印参数:在ScriptRunner脚本中打印所有传入的参数值,确保和本地测试时的参数完全一致(包括可选参数的传递方式)。
内容的提问来源于stack exchange,提问作者Piet du Preez

