文档中心MogDBMogDB StackUqbar
v5.0

文档:v5.0

支持的版本:

其他版本:

PBE模式支持存储过程out出参

可获得性

本特性自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等场景。

特性约束

  1. 该功能仅在数据库兼容模式为Oracle时能够使用(即创建DB时不指定,或DBCOMPATIBILITY='A'),在其他数据库兼容模式下不能使用该特性。

  2. JDBC版本应该大于等于5.0.0.4,JDBC端应正确连接到数据库。

  3. 仅针对表达式左值(包括存储过程参数列表中OUT/INOUT类型的数据)。

  4. 用户执行的匿名块中,变量不应该以“$”开头作为命名,如“$1”,否则可能会造成数据不准确的问题。

  5. 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端获取到执行的结果并进行处理。

相关页面

behavior_compat_options基于JDBC开发

Copyright © 2011-2024 www.enmotech.com All rights reserved.