sql >> Base de Datos >  >> RDS >> Oracle

Nuevas líneas no deseadas al poner en cola un resultado de sqlplus en un archivo xml

Como sugirió @kfinity, esto está relacionado con el manejo de CLOB, pero también con cómo dbms_output obras. Estás leyendo el CLOB en fragmentos de 32k y escribiendo cada uno de esos fragmentos con put_line() , que agrega un carácter de nueva línea después de cada fragmento de 32k. Esos no están alineados con los saltos de línea existentes dentro de su documento XML, por lo que obtiene los saltos originales, luego los adicionales, que parecen algo aleatorios y en medio del texto, pero en realidad están en lugares predecibles.

Una solución obvia es cambiar de put_line() a put() , pero eso romperá el tamaño máximo del búfer y arrojará algo como "ORU-10028:desbordamiento de longitud de línea, límite de 32767 bytes por línea".

En lugar de leer en fragmentos fijos de 32k, puede leer una línea a la vez; el CLOB realmente no entiende las líneas como tales, pero puede buscar saltos de línea, 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;

El if busca un carácter de nueva línea, después de la posición actual. Si encuentra uno, la cantidad se calcula como el número de caracteres desde la posición actual hasta esa nueva línea (o más bien, menos uno, ya que no desea la nueva línea en sí), lee esa cantidad de caracteres y luego ajusta la posición por la cantidad leída más uno (para omitir la nueva línea, que no desea/necesita como put_line() agrega uno todavía).

Si no encuentra uno, lee hasta 32k, con suerte solo una vez; si quedan más de esos caracteres sin salto de línea, entonces hará una segunda lectura pero aún agregará esa nueva línea extra y romperá esa línea. No hay mucho que puedas hacer al respecto usando dbms_output sin embargo, deberá cambiar a utl_file escribir en el servidor en lugar de enviarlo al cliente.