【问题标题】:error calling stored procedure from java through callable statement通过可调用语句从java调用存储过程时出错
【发布时间】:2011-12-27 13:07:23
【问题描述】:

我正在编写一个调用 oracle 存储过程的简单 java 程序,但它不适用于可调用语句。

当我在 SQLDeveloper 上调用该存储过程时,

EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'XXXXX', TABNAME=>'XXXXX',
PARTNAME=>'XXXXXYYYYMM', ESTIMATE_PERCENT=>5, METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE AUTO', 
CASCADE=>TRUE, DEGREE => 4);

它工作正常。

我已经成功地在我的java代码中编写了其他调用存储过程的方法,我只是使用可调用语句来调用这个特定的存储过程。所有其他方法都是由数据库管理员创建的存储过程,而不是 oracle 系统存储过程。

Statement stmt = null;
StringBuffer sb = new StringBuffer();
CallableStatement cstmt = null;     
sb.append("CALL DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'XXXXX', TABNAME=>'XXXXX', PARTNAME=>'XXXXX");
sb.append(yyyymm);
sb.append("', ESTIMATE_PERCENT=>5, METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE AUTO', CASCADE=>TRUE, DEGREE => 4)");
cstmt = this.conn.prepareCall(sb.toString());
cstmt.execute();

这给了我这样的错误。

java.sql.SQLException: ORA-06576 : not a valid function or procedure name.
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:218)
at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:969)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3476)
at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:4400)
at xxxxx.bo.batch.SYS010.SYS010.start(SYS010.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at framework.utility.classloader.DynamicClassLoader.execute(DynamicClassLoader.java:91)
at com.xxxxx.batch.module.Job.jobStart(Job.java:249)
at com.xxxxx.batch.module.Job.run(Job.java:300)

谁能告诉我真正的问题可能是什么? 从 java 源代码调用 DBMS_STATS 时有人有同样的错误吗? 这是因为我在函数调用中传递的变量吗? 我正在使用与 java 程序和 sqldeveloper 相同的 oracle 用户帐户。

【问题讨论】:

  • 我可以重现您在上面遇到的错误的唯一方法是如果我故意拼错存储过程名称。
  • 是的,我知道。我已经仔细检查和三次检查,但没有错字。还在日志文件上打印出我真正调用的内容,唯一的区别是来自 SQLDeveloper 的 CALL 而不是 EXEC。我还在 SQLDeveloper 上使用 CALL 而不是 EXEC 尝试了相同的 sql,它给了我相同的错误消息。

标签: java sql oracle stored-procedures


【解决方案1】:

似乎 Oracle 的“调用”语法要求将语句括在大括号中。请参阅OracleCallableStatement 提供的示例。请注意调用语句周围的 {}(在上面的示例中缺失):

CallableStatement cs1 = conn.prepareCall( "{call proc (?,?)}" ) ;

该示例还演示了绑定变量的用法。

【讨论】:

  • conn.prepareStatement一起工作或我 - 只要我把电话放在大括号里。示例:{ call dbms_stats.gather_index_stats(ownname=>NULL, indname=>'some_index_name') }
【解决方案2】:

如果您用 PL/SQL 块替换 CALL 是否有帮助,即

sb.append("BEGIN");
sb.append("  DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'XXXXX', TABNAME=>'XXXXX', PARTNAME=>'XXXXX");
sb.append(yyyymm);
sb.append("', ESTIMATE_PERCENT=>5, METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE AUTO', CASCADE=>TRUE, DEGREE => 4);");
sb.append("END;");

?

(注意存储过程调用后的额外分号。)

【讨论】:

  • 非常感谢卢克,我会尝试发布它的进展情况。
  • 是的,它有效。非常感谢卢克。但我仍然想知道为什么 call 不适用于这个特定的语句。
【解决方案3】:

你可以像这样从java代码调用过程:

"select GATHER_TABLE_STATS('XXXX','XXXX','XXXX') from dual" 执行。

HTH。

【讨论】:

  • 不,你不能。 DBMS_STATS.GATHER_TABLE_STATS 是一个过程,而不是一个函数,所以你不能像这样从 SQL 中调用它。
猜你喜欢
  • 2014-11-23
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多