Não adianta tentar gerar XML muito grande em PL/SQL. O problema não é o PL/SQL como tal, mas o PL/SQL só suporta XML DOM, e o DOM não lida bem com XML grande. Você não diz o tamanho do documento XML que possui, mas não ficaria surpreso ao descobrir que a memória usada pelo PL/SQL para construir seu documento é cerca de 10 a 30 vezes o tamanho do documento resultante.
Existe uma opção para gerar o XML usando algo diferente de PL/SQL? Se não, e eu realmente tive que gerar grandes arquivos XML em um banco de dados Oracle, eu consideraria usar procedimentos armazenados Java. Esta pergunta tem algumas respostas sobre como fazer esse tipo de coisa em Java.
EDITAR em resposta ao seu comentário:seu código definitivamente não está escrevendo uma linha de cada vez. Ele está escrevendo o lote junto, fato que verifiquei executando-o usando a consulta
SELECT * FROM all_objects
no meu banco de dados Oracle 11g XE. O loop foi executado uma vez e escreveu 7.341 objetos, criando um arquivo XML com pouco mais de 3 MB de tamanho. Em seguida, tentei modificar seu código para oferecer melhor suporte à abordagem 'incremental' que você descreve. Isso envolveu:
-
adicionando uma linhadbms_xmlgen.setmaxrows(ctx, max_rows);
para dizer ao DBMS_XMLGEN para gerar apenas 5 linhas por vez. Caso contrário, ele tenta gerar o lote de uma só vez.
-
modificando o código na parte superior doWHILE
loop para
xml_result := dbms_xmlgen.getXML(ctx); num_rows_processed := DBMS_XMLGEN.GETNUMROWSPROCESSED(ctx); dbms_output.put_line('Got ' || num_rows_processed || ' rows processed'); while num_rows_processed > 0 -- rest of loop omitted
-
adicionando a primeira dessas três linhas antes da parte inferior doWHILE
ciclo.
Em seguida, executei novamente seu código e pude vê-lo gravando cada lote de cinco linhas no arquivo a cada vez. No entanto, há um pequeno problema com essa abordagem, pois o arquivo foi substituído a cada vez. No final, eu tinha apenas um único registro no arquivo XML de saída. Eu não posso imaginar que isso seria o que você quer.
O
WRITETOCLOB
, WRITETOBUFFER
e WRITETOFILE
métodos em DBMS_XMLDOM
não sugerem a capacidade de anexar a um arquivo existente e, para ser honesto, não estou surpreso que eles não o façam. Se você pudesse, acabaria com um XML inválido, pois haveria mais de um <?xml ... ?>
declaração no arquivo. Eu mantenho meu conselho anterior. Sempre que você precisar lidar com XML grande, em um banco de dados Oracle ou em outro lugar, use SAX ou StAX. PL/SQL também não suporta, então faça o que for necessário em procedimentos armazenados Java ou faça-o fora do banco de dados.