Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Nhận đầu ra từ dbms_output.get_lines bằng JDBC

Tôi cũng đã viết blog về vấn đề này ở đây. Đây là đoạn mã minh họa cách thực hiện điều này:

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();
    }
}

Ở trên sẽ in:

[abc, hello, so cool, null]

Lưu ý rằng ENABLE / DISABLE cài đặt là một cài đặt rộng kết nối, vì vậy bạn cũng có thể thực hiện việc này qua một số câu lệnh 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;");
    }
}

Cũng lưu ý rằng điều này sẽ tìm nạp kích thước cố định tối đa là 1000 dòng. Bạn có thể cần lặp trong PL / SQL hoặc thăm dò ý kiến ​​cơ sở dữ liệu nếu bạn muốn thêm dòng.

Lưu ý khi gọi DBMS_OUTPUT.GET_LINE thay vào đó

Trước đây, có một câu trả lời hiện đã bị xóa đề xuất các cuộc gọi riêng lẻ tới DBMS_OUTPUT.GET_LINE thay vào đó, trả về một dòng tại một thời điểm. Tôi đã đánh giá chuẩn phương pháp so sánh nó với DBMS_OUTPUT.GET_LINES và sự khác biệt là rất lớn - chậm hơn tới 30 lần khi được gọi từ JDBC (ngay cả khi không thực sự có sự khác biệt lớn khi gọi các thủ tục từ PL / SQL).

Vì vậy, phương pháp truyền dữ liệu hàng loạt sử dụng DBMS_OUTPUT.GET_LINES chắc chắn là giá trị nó. Đây là một liên kết đến điểm chuẩn:

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




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách tạo người dùng trong Oracle và chỉ định đặc quyền

  2. Cài đặt Oracle 9i Developer Suite 2.0 trên Windows

  3. Tìm các hàng không chứa dữ liệu số trong Oracle

  4. Làm cách nào để xóa các bản sao khỏi danh sách được phân tách bằng dấu phẩy bằng regexp_replace trong Oracle?

  5. Sự khác biệt giữa LockModeType Jpa