Oracle
 sql >> Database >  >> RDS >> Oracle

Nuove righe indesiderate durante lo spooling di un risultato sqlplus in un file xml

Come suggerito da @kfinity, questo è correlato alla gestione del CLOB, ma anche a come dbms_output lavori. Stai leggendo il CLOB in blocchi di 32k e scrivendo ciascuno di questi blocchi con put_line() , che aggiunge un carattere di nuova riga dopo ogni blocco di 32k. Questi non sono allineati con alcuna interruzione di riga esistente all'interno del documento XML, quindi ottieni le interruzioni originali, quindi quelle extra, che appaiono in qualche modo casuali e a metà testo, ma in realtà si trovano in luoghi prevedibili.

Una soluzione ovvia è passare da put_line() a put() , ma ciò interromperà la dimensione massima del buffer e genererà qualcosa come "ORU-10028:overflow della lunghezza della linea, limite di 32767 byte per riga".

Invece di leggere in blocchi fissi di 32k, potresti leggere una riga alla volta; il CLOB non comprende davvero le linee in quanto tali, ma puoi cercare interruzioni di riga, qualcosa come:

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;

Il if cerca un carattere di nuova riga, dopo la posizione corrente. Se ne trova uno, l'importo viene calcolato come il numero di caratteri dalla posizione corrente a quella nuova riga (o meglio, meno uno - poiché non si desidera la nuova riga stessa), legge quel numero di caratteri e quindi regola la posizione per l'importo letto più uno (per saltare la nuova riga - che non vuoi / non ti serve come put_line() ne aggiunge ancora uno).

Se non ne trova uno, legge fino a 32k, si spera solo una volta; se sono rimasti più caratteri senza interruzioni di riga, eseguirà una seconda lettura ma aggiungerà comunque quella nuova riga extra canaglia e interromperà quella riga. Non puoi farci molto usando dbms_output tuttavia, dovresti passare a utl_file scrivere sul server invece di eseguire lo spooling sul client.