É o uso de DBMS_LOB necessária ao retornar CLOB do procedimento PL / SQL?
-
06-07-2019 - |
Pergunta
Eu gostaria de criar alguns procedimentos PL / SQL que XML retorno como parâmetros CLOB. Quero apenas fazer isso (que funciona bem com testes simples):
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;
Mas eu tenho acesso a algum outro código-fonte que faz basicamente isso:
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;
Eu estou querendo saber se o primeiro método irá causar quaisquer problemas para mim no caminho. É ok para fazê-lo dessa forma? Qual é a vantagem, se houver, para o segundo método? Obrigado!
Solução
Eu acho que você deve medir o desempenho de ambos os métodos, executando-os muitas vezes em um loop. Eu acho que o desempenho é a única diferença. Seu bloco de xml é curta, mas quando você concatenar um bloco de xml grande que é mais rápido para concatenar com dbms_low.writeappend do que usar ||.
(pelo menos era no Oracle 9, acredito que a diferença de desempenho é menor no Oracle 10.)
Outras dicas
Eu corri os seguintes procedimentos para comparar o tempo de execução:
Versão 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;
Version 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;
A diferença é neglible. Ambos vêm em em cerca de 0,2 segundo de forma consistente.
Se eu mudar os procedimentos para loop para 999999 em vez de 10000, versão 1 de começos de desempenho a diminuir ligeiramente (cerca de 39 segundos versus 32 segundos para version2).
Eu não vejo nenhuma razão pela qual você gostaria de usar o segundo.
Se lv_xml era um VARCHAR2 em vez de um CLOB então eu vejo uma razão muito boa (o comprimento máximo de um literal de cadeia vs o comprimento máximo de um CLOB).
Obrigado pelas respostas. Com base no que eu li no site listado abaixo, eu vou assumir que é de fato uma coisa boa para uso dbms_lob.writeappend. Se eu não fizer isso, eu poderia muito bem estar usando VARCHAR2s (que não será grande o suficiente em alguns casos).
Se você tem uma variável CLOB chamado "l_clob", e você faz algo como "l_clob: = l_clob || l_some_string_to_concatenate;", ele irá converter o valor l_clob no lado direito da equação para um VARCHAR2 antes de fazer a concatenação , possivelmente dando-lhe resultados inválidos ou um erro.
Não há outra opção que você não mencionar: usando Oracle built-in funcionalidade XML (presumindo que você tem uma versão de banco de dados de 9i ou superior). Por exemplo, gerando um documento XML a partir de uma consulta é um recorte com DBMS_XMLGEN.getXML()
ou DBMS_XMLGEN.getXMLType()
.