使用JDBC从dbms_output.get_lines获取输出

如何在使用数据库创建其他对象的情况下使用JDBC从Java应用程序中获取Oracle dbms_output.get_lines的输出?

我也在这里写了关于这个问题的博客 。 这是一个片段,说明了如何做到这一点:

 try (CallableStatement call = c.prepareCall( "declare " + " num integer := 1000;" // Adapt this as needed + "begin " // You have to enable buffering any server output that you may want to fetch + " dbms_output.enable();" // This might as well be a call to third-party stored procedures, etc., whose // output you want to capture + " dbms_output.put_line('abc');" + " dbms_output.put_line('hello');" + " dbms_output.put_line('so cool');" // This is again your call here to capture the output up until now. // The below fetching the PL/SQL TABLE type into a SQL cursor works with Oracle 12c. // In an 11g version, you'd need an auxiliary SQL TABLE type + " dbms_output.get_lines(?, num);" // Don't forget this or the buffer will overflow eventually + " dbms_output.disable();" + "end;" )) { call.registerOutParameter(1, Types.ARRAY, "DBMSOUTPUT_LINESARRAY"); call.execute(); Array array = null; try { array = call.getArray(1); System.out.println(Arrays.asList((Object[]) array.getArray())); } finally { if (array != null) array.free(); } } 

以上将打印:

 [abc, hello, so cool, null] 

请注意, ENABLE / DISABLE设置是连接范围设置,因此您也可以通过多个JDBC语句执行此操作:

 try (Connection c = DriverManager.getConnection(url, properties); Statement s = c.createStatement()) { try { s.executeUpdate("begin dbms_output.enable(); end;"); s.executeUpdate("begin dbms_output.put_line('abc'); end;"); s.executeUpdate("begin dbms_output.put_line('hello'); end;"); s.executeUpdate("begin dbms_output.put_line('so cool'); end;"); try (CallableStatement call = c.prepareCall( "declare " + " num integer := 1000;" + "begin " + " dbms_output.get_lines(?, num);" + "end;" )) { call.registerOutParameter(1, Types.ARRAY, "DBMSOUTPUT_LINESARRAY"); call.execute(); Array array = null; try { array = call.getArray(1); System.out.println(Arrays.asList((Object[]) array.getArray())); } finally { if (array != null) array.free(); } } } finally { s.executeUpdate("begin dbms_output.disable(); end;"); } } 

另请注意,这将最多获取1000行的固定大小。 如果需要更多行,可能需要循环PL / SQL或轮询数据库。

关于调用DBMS_OUTPUT.GET_LINE的说明

以前,有一个现在删除的答案,建议单独调用DBMS_OUTPUT.GET_LINE ,它一次返回一行。 我对比较它与DBMS_OUTPUT.GET_LINES的方法进行了基准测试,差异很大 – 从JDBC调用时速度慢了30倍(即使从PL / SQL调用过程时没有太大的区别)。

因此,使用DBMS_OUTPUT.GET_LINES的批量数据传输方法绝对值得。 这是基准的链接:

https://blog.jooq.org/2017/12/18/the-cost-of-jdbc-server-roundtrips/