Необходимо ли использовать DBMS_LOB при возврате CLOB из процедуры PL / SQL?

StackOverflow https://stackoverflow.com/questions/1613408

Вопрос

Я хотел бы создать несколько процедур PL / SQL, которые возвращают XML в качестве параметров CLOB. Я хочу просто сделать это (что хорошо работает с простыми тестами):

create or replace procedure p_xml_test_1(
  p_xml out nocopy clob
) is
begin
  p_xml := '<?xml version="1.0" encoding="utf8" ?>' ||
    '<test><something>some value</something></test>';
end p_xml_test_1;

Но у меня есть доступ к другому исходному коду, который в основном делает это:

create or replace procedure p_xml_test_2(
  p_xml out nocopy clob
) is
  lv_xml clob;
begin
  dbms_lob.createtemporary(
    lob_loc => p_xml,
    cache   => true
  );

  lv_xml := '<?xml version="1.0" encoding="utf8" ?>' ||
    '<test><something>some value</something></test>';

  dbms_lob.writeappend(
    lob_loc => p_xml,
    amount  => length(lv_xml),
    buffer  => lv_xml
  );
end p_xml_test_2;

Мне интересно, вызовет ли первый метод какие-либо проблемы для меня в будущем. Можно ли так делать? В чем преимущество второго метода? Спасибо!

Это было полезно?

Решение

Я думаю, что вы должны измерить производительность обоих методов, запустив их много раз в цикле. Я думаю, что производительность - единственная разница. Ваш xml-блок короткий, но когда вы объединяете большой xml-блок, быстрее объединить его с dbms_low.writeappend, чем с помощью ||.

(По крайней мере, это было в Oracle 9, я думаю, что разница в производительности меньше в Oracle 10.)

Другие советы

Я выполнил следующие процедуры для сравнения времени выполнения:

Версия 1

create or replace procedure p_xml_test_1(
  p_xml out nocopy clob
) is
  lv_i number;
begin
  for lv_i in 1 .. 999999 loop
    p_xml := p_xml || 'a';
  end loop;
end p_xml_test_1;

Версия 2

create or replace procedure p_xml_test_2(
  p_xml out nocopy clob
) is
  lv_xml clob;
  lv_i   number;
begin
  dbms_lob.createtemporary(
    lob_loc => p_xml,
    cache   => true
  );

  for lv_i in 1 .. 999999 loop
    lv_xml := 'a';

    dbms_lob.writeappend(
      lob_loc => p_xml,
      amount  => length(lv_xml),
      buffer  => lv_xml
    );
  end loop;
end p_xml_test_2;

Разница незначительная. Оба поступают примерно за 0,2 секунды последовательно.

Если я переключу процедуры на цикл 999999 вместо 10000, производительность версии 1 начнет несколько снижаться (примерно 39 секунд против 32 секунд для версии 2).

Я не вижу причин, почему вы хотели бы использовать второй.

Если lv_xml был VARCHAR2, а не CLOB, я вижу очень вескую причину (максимальная длина строкового литерала против максимальной длины CLOB).

Спасибо за ответы. Исходя из того, что я прочитал на сайте, указанном ниже, я собираюсь предположить, что на самом деле полезно использовать dbms_lob.writeappend. Если я этого не сделаю, я мог бы также использовать VARCHAR2 (который в некоторых случаях будет недостаточно большим).

  

Если у вас есть переменная CLOB с именем «l_clob» и вы делаете что-то вроде «l_clob: = l_clob || l_some_string_to_concatenate; " ;, он преобразует значение l_clob в правой части уравнения в VARCHAR2 перед выполнением конкатенации, что может привести к неверным результатам или ошибке.

http://www.maristream.org/srea/Huge_Strings_Using_LOBs.htm

Есть еще одна опция, которую вы не упомянули: использование встроенной в Oracle функциональности XML (при условии, что у вас версия базы данных 9i или выше). Например, создание XML-документа из запроса - это фрагмент кода с помощью DBMS_XMLGEN.getXML () или DBMS_XMLGEN.getXMLType () .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top