使用带有布尔IN参数的CallableStatement在Java中调用Oracle PL/SQL过程会产生PLS-00306 oracle错误:

zig*_*ggy 12 java sql oracle plsql jdbc

我在Oracle 11g上有一个pl/sql过程,它具有以下参数:

PROCEDURE validate_product
   ( product_id_in IN varchar2 , 
     username_in in varchar2, 
     source_in varchar2,    
     source_id_in varchar2 , 
     isEuProduct in boolean , 
     error_code out varchar2, 
     product_type out varchar2  
     )
Run Code Online (Sandbox Code Playgroud)

我试图使用以下代码从java中调用上面的存储过程:

cstmt = getConnection().prepareCall("begin " + DBUtil.SCHEMANAME + ".PRODUCT_UTILITIES.validate_product(:1,:2,:3,:4,:5,:6,:7); end;");

cstmt.registerOutParameter(6, Types.CHAR); 
cstmt.registerOutParameter(7, Types.CHAR); 

cstmt.setString(1, productId);
cstmt.setString(2, username);
cstmt.setString(3, sourceName);
cstmt.setString(4, sourceId);
cstmt.setBoolean(5, isEUProduct);

cstmt.execute();
Run Code Online (Sandbox Code Playgroud)

该类型的Java变量都String以异常的isEUProductboolean.每当我运行上述程序时,我都会收到以下错误:

PLS-00306: wrong number or types of arguments in call to validate_product ORA-06550: line 1, column 7: PL/SQL: Statement ignored"
Run Code Online (Sandbox Code Playgroud)

我必须调试程序一百次,但一切似乎都是正确的类型,参数的数量是正确的.

我完全不知道我做错了什么.谷歌搜索我怀疑我可能没有正确设置布尔参数.

有任何想法吗?

Ste*_*e K 24

当我们碰到这个时,我感到很惊讶,但是Oracle JDBC驱动程序不支持将布尔值传递给存储过程....雅,我不是这样做的:)

PL/SQL存储过程中的布尔参数

JDBC驱动程序不支持将BOOLEAN参数传递给PL/SQL存储过程.如果PL/SQL过程包含BOOLEAN值,则可以通过将PL/SQL过程与第二个接受该参数作为INT的PL/SQL过程一起包装并将其传递给第一个存储过程来解决该限制.调用第二个过程时,服务器执行从INT到BOOLEAN的转换.


GWu*_*GWu 6

该限制有一个简单的解决方法,它不需要包装过程,只需将 PL/SQL 中的布尔参数包装在CASE语句中,并使用 Integer 进行绑定:

stmt = connection.prepareCall("begin" 
        +"  booleanFunc(par_bool => (CASE ? WHEN 1 THEN TRUE ELSE FALSE END)); "
        +"end;"
       );

// now bind integer, 1 = true, 0 = false
stmt.setInt(1, 0); // example for false
Run Code Online (Sandbox Code Playgroud)

如果您的方法使用布尔值,您可以在绑定期间以相反的方式包装 Integer,例如:

// now bind integer, 1 = true, 0 = false
stmt.setInt(1, myBool ? 1 : 0); 
Run Code Online (Sandbox Code Playgroud)


Max*_*Max 1

我怀疑 out 语句可能需要修改以下内容(因为过程中 out 参数的类型是 varchar2):-

cstmt.registerOutParameter(6, Types.VARCHAR); 
cstmt.registerOutParameter(7, Types.VARCHAR); 
Run Code Online (Sandbox Code Playgroud)

但是,如果这不起作用,请尝试将prepareCall语句也修改为以下内容:-

cstmt = getConnection().prepareCall("{call " + DBUtil.SCHEMANAME + ".PRODUCT_UTILITIES.validate_product(?,?,?,?,?,?,?)}");
Run Code Online (Sandbox Code Playgroud)