UTL_FILE.WRITE_ERROR when calling utl_file.put in a loop

前端 未结 2 999
执念已碎
执念已碎 2021-01-20 00:17

I have below code in my PL/SQL procedure, which I called in API_XXX.put(it calls utl_file.put) in a while loop. And the l_xmldoc is CLOB from a function of getR

相关标签:
2条回答
  • 2021-01-20 00:50

    Just a guess, but instead of "to_char(10)" you might try chr(10) to determine/write a newline. Not sure if this will solve your problem, but sometimes very long lines (without newlines) can cause issues.

    For example:

    declare
        l_clob clob;
        l_char char;
    begin
        l_clob := 'Line 1' || chr(10) || 'Line 2' || chr(10);
    
        for i in 1 .. DBMS_LOB.GETLENGTH(l_clob)
        loop
            l_char := dbms_lob.substr(l_clob, 1, i);
    
            if (l_char = chr(10)) then
            --if (l_char = to_char(10)) then
                dbms_output.put_line('Found a newline at position ' || i);
            end if;
        end loop;
    
    end;
    

    Notice the difference between chr(10) and to_char(10). Easy enough to test if this solves your problem anyway.

    0 讨论(0)
  • 2021-01-20 00:58
    1. Post the Oracle Version you are using! Or we can just guess around...

    2. Your fflush will not work as you expect - From the documentation:

      FFLUSH physically writes pending data to the file identified by the file handle. Normally, data being written to a file is buffered. The FFLUSH procedure forces the buffered data to be written to the file. The data must be terminated with a newline character.

    3. tbone is abolutely right the line TO_CHAR(10) is wrong! Just try SELECT TO_CHAR(10) FROM DUAL; you will get 10 which you then compare to a single character. A single character will never be '10' since 10 has two characters!

    4. Your problem is most likely a buffer-overflow with too large XML-Files, but keep in mind, also other problems on the target system can lead to write_errors, which should be handled.

    Solutions

    • Quick&Dirty: Since you don't seem to care about performance anyways you can just close the file every X byte and reopen it with A for append. So just add to the loop:

      IF MOD( l_offset, 32000 ) = 0
      THEN
        UTL_FILE.FCLOSE( f_out );
        UTL_FILE.FOPEN( out_fpath, out_fname, f_out, 'a', 32767 );
      END IF;
      
    • Use the right tool for the right job: UTL_FILE is not suited for handling complex data. The only usecase for UTL_FILE are small newline-separated lines of text. For everything else you should write RAW bytes! (Which will also allow you porper control over ENCODING, which is currently just mini-vanilly-lucky-guess)

    • Write a Java-Stored-Procedure with NIO-Filechannels - fast, safe, nice... But be careful, your program might run 10 times as fast!

    0 讨论(0)
提交回复
热议问题