Необходимо ли использовать DBMS_LOB при возврате CLOB из процедуры PL / SQL?
-
06-07-2019 - |
Вопрос
Я хотел бы создать несколько процедур 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 ()
. Р>