CREATE OR REPLACE FUNCTION F_EXPORT2XML RETURN INTEGER IS
RESULT INTEGER := 0;
XMLSTRING CLOB := NULL;
AMOUNT INTEGER := 32767;
POSITION INTEGER := 1;
CHARSTRING VARCHAR2(32767) := '';
IDX_CHR10 INTEGER;
LEN INTEGER;
WRITESTRING VARCHAR2(32767);
FILEHANDLE UTL_FILE.FILE_TYPE;
XMLHDL DBMS_XMLGEN.CTXTYPE;
SQLERRTEXT VARCHAR2(32767);
BEGIN
XMLHDL := DBMS_XMLGEN.NEWCONTEXT('SELECT * FROM XXXXl');
--open the file in "write" mode
FILEHANDLE := UTL_FILE.FOPEN('EXPDIR', 'XML_XXXX.XML', 'w');
XMLSTRING := DBMS_XMLGEN.GETXML(XMLHDL);
--Now open the lob data..
DBMS_LOB.OPEN(XMLSTRING, DBMS_LOB.LOB_READONLY);
LOOP
-- read the lob data
DBMS_LOB.READ(XMLSTRING, AMOUNT, POSITION, CHARSTRING);
IDX_CHR10 := INSTR(CHARSTRING, CHR(10), -1);
LEN := LENGTH(CHARSTRING);
IF (IDX_CHR10 < LEN AND IDX_CHR10 > 0) THEN
WRITESTRING := SUBSTR(CHARSTRING, 1, IDX_CHR10 - 1);
ELSE
WRITESTRING := SUBSTR(CHARSTRING, 1, LEN - 1);
END IF;
UTL_FILE.PUT_LINE(FILEHANDLE, WRITESTRING);
POSITION := POSITION + IDX_CHR10;
END LOOP;
RESULT := 1;
RETURN(RESULT);
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- end of fetch, free the lob
DBMS_LOB.CLOSE(XMLSTRING);
DBMS_LOB.FREETEMPORARY(XMLSTRING);
IF UTL_FILE.IS_OPEN(FILEHANDLE) THEN
UTL_FILE.FCLOSE(FILEHANDLE);
END IF;
RETURN(RESULT);
WHEN OTHERS THEN
SQLERRTEXT := SQLERRM;
IF UTL_FILE.IS_OPEN(FILEHANDLE) THEN
UTL_FILE.FCLOSE(FILEHANDLE);
END IF;
RETURN(RESULT);
END F_EXPORT2XML;
经测试,效率比我写的上一个版本至少提供1倍,可能在某些特殊情况下,还是会出现异常,不过不影响大局了。