Обновленный ответ выглядит великолепно и подтвержден для работы с Oracle 10, 11 и 12.

ожно получить вывод от Oracledbms_output.get_lines в приложении Java с использованием JDBCбез создания дополнительных объектов в базе данных?

 Axel Fontaine15 дек. 2017 г., 11:45
@AlexPoole Спасибо. Я только пояснил вопрос, добавив «без создания дополнительных объектов в базе данных», так как эти права, скорее всего, не будут предоставлены.
 Alex Poole15 дек. 2017 г., 11:43
Вы могли бы сделатьэто (что требует нового типа) илиэто (который использует встроенные типы); а затем позвонить одному из тех, кто через JDBC? Или естьэтот пост от Тома Кайта? Таблица регистрации может быть более подходящей. Зависит именно то, что вам нужно для достижения.
 Ravinder Reddy15 дек. 2017 г., 11:33
это может помочьcommunity.oracle.com/thread/104787
 William Robertson15 дек. 2017 г., 11:46
Обратите внимание, что в последних версиях Oracle,dbms_output.get_lines перегружен и может вернутьdbmsoutput_linesarray, который должен быть более дружественным к JDBC, чем старыйdbms_output.chararray.
 Axel Fontaine15 дек. 2017 г., 11:40
@RavinderReddy Нет, это не так. Этот пост древний, и там нет никакого решения.

Ответы на вопрос(1)

Решение Вопроса

Я также написал в блоге об этой проблеме здесь, Вот фрагмент, который иллюстрирует, как это можно сделать:

    "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;");

        
            "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и различия резко - до 30 раз медленнее при вызове из JDBC (даже если при вызове процедур из PL / SQL нет большой разницы).

Таким образом, подход массовой передачи данных с использованиемDBMS_OUTPUT.GET_LINES определенно стоит того. Вот ссылка на тест:

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

 Lukas Eder15 дек. 2017 г., 14:35
@WilliamRobertson: Вы, вероятно, имеете в видуdbmsoutput_linesarray, Вы правы. Я упустил тот факт, что это тип уровня схемы. Исправлю мой ответ.
 William Robertson15 дек. 2017 г., 13:30
Но вам не нужен тип таблицы PL / SQL. Конечно, JDBC может обрабатывать типы коллекций SQL на уровне схемы?
 Lukas Eder15 дек. 2017 г., 13:08
@WilliamRobertson: Вы не поверите, как долго Oracle игнорирует этот запрос! Очевидно, драйвер JDBC Oracle 12cR2 может передавать типы таблиц PL / SQL. Я еще не играл с этим, поэтому я опустил это в ответ. Точно так же это заняло ихнавсегда поддерживать тип PL / SQL BOOLEAN из JDBC (и вы все еще не можете использовать эти типы из обычных операторов SQL). Псих!
 Axel Fontaine15 дек. 2017 г., 17:04
Обновленный ответ выглядит великолепно и подтвержден для работы с Oracle 10, 11 и 12.
 William Robertson15 дек. 2017 г., 12:52
Это стандартный способ вызова процедуры, которая возвращает общедоступную коллекцию SQL? Похоже, это было бы обычным делом в приложениях Java, которые взаимодействуют с Oracle.

Ваш ответ на вопрос