這裏比較推薦第壹種方式,便於數據及文件管理,方便導入導出,缺點是容易造成數據與文件內容不壹致,文件管理與ORACLE關系不大。
重點說壹下第二種方式即BLOB\CLOB方式,對於內容不大的可直接存取BLOB,太大的文件借助目錄文件。
reate or replace procedure TEST_BLOB_INS (FBuffer IN VARChAR2) IS
DEST_LOB BLOB;
WRITE_AMOUNT INTEGER ;
BEGIN
--FILE_CONTENT為指定大字段
UPDATE XXTABLE SET FILE_CONTENT=EMPTY_BLOB() WHERE ID= 999 ;
SELECT FILE_CONTENT INTO DEST_LOB FROM XXTABLE WHERE ID = 999 FOR UPDATE;
DBMS_LOB.OPEN(DEST_LOB,DBMS_LOB.LOB_READWRITE);
WRITE_AMOUNT := LENGTHB(WR_BUFFER) ;
DBMS_LOB.WRITE(DEST_LOB, WRITE_AMOUNT, 1, UTL_RAW.cast_to_raw(WR_BUFFER));
DBMS_LOB.CLOSE(DEST_LOB);
COMMIT;
END TEST_BLOB;
借助目錄方式在存取:
具體過程:
A,首先請DBA在控制臺創建目錄記錄
CREATE OR REPLACE DIRECTORY MY_DIR as '/home/jsp';
-- 可使用 select * from dba_directories 進行查詢是否創建成功;
B,再將新建的MY_DIR目錄別名授權給指定用戶使用
GRANT READ,WRITE on DIRECTORY MY_DIR TO user_cms ;
C,將擬存入數據庫的文件上傳至服務器的/home/jsp目錄下
D,再使用以下過程進行文件讀出並寫入數據庫, FName 為文件名, RecID為指定表記錄的ID
create or replace procedure TEST_BLOB_FILEINS(RECID IN INTEGER,FName IN VARCHAR2) IS
DEST_LOB BLOB;
V_FILE BFILE ;
V_Fsize INTEGER ;
BEGIN
V_FILE := BFILENAME('MY_DIR', FName);
UPDATE xxTAble SET FILE_CONTENT=EMPTY_BLOB() WHERE ID= RECID RETURN FILE_CONTENT INTO DEST_LOB;
v_FSize := DBMS_LOB.GETLENGTH(v_file);
DBMS_OUTPUT.PUT_LINE('File size: ' || v_Fsize);
DBMS_LOB.FILEOPEN(V_FILE);
DBMS_LOB.LOADFROMFILE(DEST_LOB, V_FILE, DBMS_LOB.LOBMAXSIZE);
DBMS_LOB.FILECLOSEALL;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('在更新BLOB內容時不成功,ID=' || RECID ) ;
END TEST_BLOB;
數據提取過程
create or replace procedure download_blob(srcname varchar2, dstname varchar2) as
mount binary_integer := 32767;
fbuffer raw(32767);
utlfile utl_file.file_type;
dumpfile blob;
pos integer := 1;
len binary_integer;
begin
select blob_file into dumpfile from blob_tb where data_name = srcname;
len := dbms_lob.getlength(dumpfile);
utlfile := utl_file.fopen('MY_DIR', dstname, 'wb', 32767);
while pos < len loop
dbms_lob.read(dumpfile, mount, pos, fbuffer);
utl_file.put_raw(utlfile, fbuffer, true);
pos := pos + mount;
end loop;
utl_file.fclose(utlfile);
end;