摘要:
用戶提出一個需求,即ORACLE中的一個表存儲了照片信息,字段類型爲BLOB,要求能導出成文件形式. 本想寫個C#程序來做,後來想起ORACLE有很多包,功能很好很強大,於是網上參考了些文章完成了. 主要是用了ORACLE的兩個包:UTL_FILE和DBMS_LOB.
實現過程:
第一步:以管理員用戶登陸設置可操作目錄
create or replace directory BLOBDIR as 'D:\PIC';
grant read,write on directory BLOBDIR to sharedb;
GRANT EXECUTE ON utl_file TO sharedb;
select * from ALL_DIRECTORIES;
第二步:普通用戶登陸,編寫存儲過程
CREATE OR REPLACE PROCEDURE GET_PIC_BLOB (i_xh VARCHAR2) IS
l_file UTL_FILE.FILE_TYPE;
l_buffer RAW(32767);
l_amount BINARY_INTEGER := 32767;
l_pos INTEGER := 1;
l_blob BLOB;
l_blob_len INTEGER;
BEGIN
SELECT PIC INTO L_BLOB FROM TB_ZP WHERE PSNNO = i_xh;
l_blob_len := DBMS_LOB.GETLENGTH(l_blob);
l_file := UTL_FILE.FOPEN('BLOBDIR',i_xh || '.jpg','WB',32767);
WHILE l_pos < l_blob_len LOOP
DBMS_LOB.READ (l_blob, l_amount, l_pos, l_buffer);
UTL_FILE.PUT_RAW(l_file, l_buffer, TRUE);
l_pos := l_pos + l_amount;
END LOOP;
UTL_FILE.FCLOSE(l_file);
EXCEPTION
--WHEN NO_DATA_FOUND THEN
--DBMS_OUTPUT.put_line('no data : ' || i_xh);
WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN(l_file) THEN
UTL_FILE.FCLOSE(l_file);
RAISE;
END IF;
END GET_PIC_BLOB;
第三步:編寫PL/SQL 塊,循環執行該存儲過程
cursor cur_01 is
select xh from xs_xsjbk where rownum <= 5000 ;
begin
for rec_01 in cur_01 loop
GET_PIC_BLOB(rec_01.xh);
end loop;
end;
測試結果.取了5000條數據,其中有照片信息的爲3407條.用時1分12秒,感覺還可以.
總結:
1.由管理員創建可訪問目錄和授權給普通用戶比較重要,一開始沒有注意,總是報非法路徑錯誤,搞了較長時間在這上面.
2.存儲過程中的NO_DATA_FOUND異常本來是屏顯輸出無照片的學號信息,但是實際運行時出錯,原因是DBMS_OUTPUT.put_line打印條數過多,於是註釋掉了.
3.Oracle本身提供了大量使用的包,如UTL_HTTP,DBMS_OUTPUT等,分別封裝了不同的功能,進行大量的應用程序開發的可能,從而拓展了Oracle的功能.