sql >> Database >  >> RDS >> Oracle

Ongewenste nieuwe regels bij het spoolen van een sqlplus-resultaat naar een xml-bestand

Zoals @kfinity suggereerde, heeft dit te maken met CLOB-afhandeling, maar ook met hoe dbms_output werken. Je leest de CLOB in blokken van 32k, en schrijft elk van die blokken weg met put_line() , die een teken voor een nieuwe regel toevoegt na elke 32k chunk. Die zijn niet uitgelijnd met bestaande regeleinden in uw XML-document, dus u krijgt de originele onderbrekingen en daarna extra - die enigszins willekeurig lijken en midden in de tekst staan, maar zich in feite op voorspelbare plaatsen bevinden.

Een voor de hand liggende oplossing is om over te schakelen van put_line() naar put() , maar dat zal de maximale buffergrootte breken en zoiets als "ORU-10028:regellengteoverloop, limiet van 32767 bytes per regel".

In plaats van in vaste stukken van 32k te lezen, zou je regel voor regel kunnen lezen; de CLOB begrijpt lijnen als zodanig niet echt, maar je kunt zoeken naar regeleinden, zoiets als:

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;

De if zoekt naar een teken voor een nieuwe regel, na de huidige positie. Als het er een vindt, wordt het aantal berekend als het aantal tekens van de huidige positie tot die nieuwe regel (of liever min één - omdat je de nieuwe regel zelf niet wilt), het leest zoveel tekens en past vervolgens de positie aan door het gelezen bedrag plus één (om de nieuwe regel over te slaan - die u niet wilt/nodig hebt als put_line() voegt er nog een toe).

Als het er geen vindt, leest het tot 32k - hopelijk slechts één keer; als er meer dan dat aantal tekens over zijn zonder regeleinde, dan zal het een tweede keer lezen, maar toch die bedrieglijke extra nieuwe regel toevoegen en die regel breken. U kunt daar niet veel aan doen met dbms_output u moet echter overschakelen naar utl_file schrijven naar de server in plaats van naar de client te spoolen.




  1. Selecteer meerdere rijwaarden in één rij met clausules met meerdere tabellen

  2. Lijst met MySQL-specificaties voor datumnotatie

  3. Oracle SQL afgeleide tabel - optionele aliasing

  4. Stel de standaardoptie in in de vervolgkeuzelijst php en bewaar deze wanneer de vraag wordt ingediend