可获得性
本特性自MogDB 5.0.8版本开始引入。
特性简介
在使用JDBC等PBE连接方式的情况下,支持匿名块中的左值在存储过程中的返回值返回到对应驱动端。该功能的使用需要设置behavior_compat_options参数中proc_outparam_override选项。方法如下:
set behavior_compat_options = 'proc_outparam_override';
或在postgres.conf文件中设置此参数并重启数据库。
客户价值
提高兼容性,兼容Oracle的对应用法。提高可用性,便于编写JDBC等程序连接数据库操作。
特性描述
在使用JDBC等PBE连接方式的情况下,支持匿名块中的左值(包括存储过程参数列表中OUT/INOUT类型的数据)在存储过程中的返回值返回到对应驱动端。以JDBC举例,用户在编写匿名块程序执行时,希望将表达式的左值出参返回到java程序端并在java程序端处理这些数据。可以将匿名块中对应位置的变量替换为“?”,并在后续程序中对数据类型进行合法的注册,即可使用对应的get方法获取到。
支持的数据范围包括JDBC支持映射的基本数据类型,tableof、object、array、refcursor、composite等。
Jdbc默认数据类型映射关系参考:
get:java.sql.CallableStatement
set:java.sql.PreparedStatement
支持的场景包括匿名块直接执行、匿名块调用函数、匿名块调用存储过程、匿名块调用package,匿名块内部调用immutable execute、select into、bulk into、execute immediate、fetch into等场景。
特性约束
-
该功能仅在数据库兼容模式为Oracle时能够使用(即创建DB时不指定,或DBCOMPATIBILITY=‘A’),在其他数据库兼容模式下不能使用该特性。
-
JDBC版本应该大于等于5.0.0.4,JDBC端应正确连接到数据库。
-
仅针对表达式左值(包括存储过程参数列表中OUT/INOUT类型的数据)。
-
用户执行的匿名块中,变量不应该以“$”开头作为命名,如“$1”,否则可能会造成数据不准确的问题。
-
immutable execute场景不支持直接使用匿名块出参,因为字符串里面的”?”并不会被计算为需要替换的变量,但可以配合using使用。
示例
public static void test_case_0001_output_mutil(Connection conn) throws Exception {
String baseSQLStrings = "set behavior_compat_options='proc_outparam_override';";
String baseSQLString = "DECLARE" +
"baselen integer:= 199;" +
"BEGIN" +
"? := baselen;" +
"? := baselen*2;" +
"END;";
try {
CallableStatement pstmt = conn.prepareCall(baseSQLStrings);
pstmt.execute();
pstmt.close();
pstmt = conn.prepareCall(baseSQLString);
System.out.println("Prepare param out SQL succeed!");
pstmt.registerOutParameter(1, Types.INTEGER);
System.out.println("Register succeed!");
pstmt.registerOutParameter(2, Types.INTEGER);
System.out.println("Register succeed!");
pstmt.execute();
System.out.println("Execute succeed!");
if (199 == pstmt.getInt(1)) {
System.out.println("answer true");
} else {
System.out.println("answer false");
}
if (398 == pstmt.getInt(2)) {
System.out.println("answer true");
} else {
System.out.println("answer false");
}
System.out.println("Get succeed!");
pstmt.close();
System.out.println("Run succeed!");
}
catch (Exception e) {
String exceptionStr = e.toString();
System.out.println(exceptionStr);
}
}
以上用例中,我们在baseSQLString中使用了匿名块出参的功能,其中涉及了两次表达式左值的返回。并且可以在java端获取到执行的结果并进行处理。
public static void t02_base_test(Connection conn) throws Exception {
String createPackageHead =
"CREATE OR REPLACE PACKAGE testuser.pck2 AS" +
" PROCEDURE get_IN_OUT(output1 OUT varchar(26), output2 OUT bool, output3 OUT TINYINT, output4 OUT smallint, ret1 IN OUT DOUBLE PRECISION);" +
"END pck2;";
String createPackageBody =
"CREATE OR REPLACE PACKAGE BODY testuser.pck2 AS" +
" PROCEDURE get_IN_OUT(output1 OUT varchar(26), output2 OUT bool, output3 OUT TINYINT, output4 OUT smallint, ret1 IN OUT DOUBLE PRECISION) IS" +
" BEGIN" +
" output1 := 'abcdefghigklmnopqrstuvwxyz';" +
" output2 := false;" +
" output3 := 2;" +
" output4 := 12;" +
" ret1 := ret1 + 10;" +
" END get_IN_OUT;" +
"END pck2;";
String baseSQLString =
"BEGIN" +
" testuser.pck2.get_IN_OUT(?, ?, ?, ?, ?);" +
"END;";
try {
CallableStatement pstmt = conn.prepareCall(createPackageHead);
pstmt.execute();
pstmt.close();
System.out.println("HEAD Prepare succeed!");
pstmt = conn.prepareCall(createPackageBody);
pstmt.execute();
pstmt.close();
System.out.println("BODY Prepare succeed!");
pstmt = conn.prepareCall(baseSQLString);
pstmt.setDouble(5, 99.99999999);
pstmt.registerOutParameter(1, Types.VARCHAR);
pstmt.registerOutParameter(2, Types.BOOLEAN);
pstmt.registerOutParameter(3, Types.TINYINT);
pstmt.registerOutParameter(4, Types.SMALLINT);
pstmt.registerOutParameter(5, Types.DOUBLE);
System.out.println("Register succeed!");
pstmt.execute();
System.out.println("Execute succeed!");
System.out.println(pstmt.getString(1));
System.out.println(pstmt.getBoolean(2));
System.out.println(pstmt.getByte(3));
System.out.println(pstmt.getShort(4));
System.out.println(pstmt.getDouble(5));
System.out.println("Get succeed!");
pstmt.close();
System.out.println("Run succeed!");
}
catch (Exception e) {
String exceptionStr = e.toString();
System.out.println(exceptionStr);
}
}
以上用例中,我们在baseSQLString中使用了匿名块出参的功能,其中涉及了五种基本类型的返回与package的调用,以及OUT与INOUT类型的使用。并且可以在java端获取到执行的结果并进行处理。




