Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Novas linhas indesejadas ao enviar um resultado sqlplus para um arquivo xml


Como o @kfinity sugeriu, isso está relacionado ao manuseio de CLOB, mas também a como dbms_output funciona. Você está lendo o CLOB em pedaços de 32k e escrevendo cada um desses pedaços com put_line() , que acrescenta um caractere de nova linha após cada pedaço de 32k. Elas não estão alinhadas com nenhuma quebra de linha existente em seu documento XML, então você obtém as quebras originais e depois as extras - que aparecem um pouco aleatórias e no meio do texto, mas na verdade estão em lugares previsíveis.

Uma solução óbvia é mudar de put_line() para put() , mas isso quebrará o tamanho máximo do buffer e lançará algo como "ORU-10028:estouro de comprimento de linha, limite de 32767 bytes por linha".

Em vez de ler em pedaços fixos de 32k, você pode ler uma linha de cada vez; o CLOB realmente não entende as linhas como tal, mas você pode procurar por quebras de linha, algo como:
WHILE pos < v_clob_length LOOP
  -- read to next newline if there is one, rest of CLOB if not
  if dbms_lob.instr(v_clob, chr(10), pos) > 0 then
    amount := dbms_lob.instr(v_clob, chr(10), pos) - pos;
    dbms_lob.read(v_clob, amount, pos, buffer);
    pos := pos + amount + 1; -- skip newline character
  else
    amount := 32767;
    dbms_lob.read(v_clob, amount, pos, buffer);
    pos := pos + amount;
  end if;

  dbms_output.put_line(buffer);
END LOOP;

O if procura um caractere de nova linha, após a posição atual. Se encontrar um, o valor é calculado como o número de caracteres da posição atual para essa nova linha (ou melhor, menos um - como você não deseja a nova linha), ele lê tantos caracteres e ajusta a posição pela quantidade lida mais um (para pular a nova linha - que você não quer/precisa como put_line() adiciona um ainda).

Se não encontrar um, ele lê até 32k - espero que apenas uma vez; se houver mais do que isso, pode haver caracteres sem quebra de linha, então ele fará uma segunda leitura, mas ainda adicionará essa nova linha extra desonesta e quebrará essa linha. Não há muito o que fazer sobre isso usando dbms_output no entanto, você precisaria mudar para utl_file gravando no servidor em vez de enviar para o cliente.