達夢數據庫中插入導出圖片的方法與應用
在數據庫的實際應用場景中,圖片存儲是一項常見且重要的需求。以電商平臺為例,商品展示圖片是吸引消費者的關鍵元素;而在社交軟件里,用戶頭像更是個人形象的直觀體現。針對達夢數據庫,業界常用的圖片存儲策略主要分為兩大類。
第一種策略是將圖片存儲于磁盤,數據庫字段僅記錄圖片路徑。這種方式的顯著優勢在于減輕了數據庫的存儲壓力,因為數據庫無需直接處理圖片的二進制數據。然而,它存在明顯的局限性,一旦圖片存儲路徑發生變更,或者存儲磁盤出現故障,數據庫應用在調用圖片時就可能遭遇加載失敗的問題。例如,若存儲圖片的磁盤分區因硬件故障損壞,依賴該路徑的應用程序將無法正常顯示相關圖片。
第二種策略是將圖片以二進制形式直接存儲于數據庫。達夢數據庫采用這種方式,并支持使用 blob 或 bfile 類型的字段進行存儲。這種策略的優勢在于保障了數據的完整性和一致性,圖片數據與其他相關數據集中存儲于數據庫,便于統一管理和維護。但高分辨率圖片的二進制數據量往往較大,會顯著增加數據庫的存儲負擔。
接下來,詳細介紹在 達夢數據庫中利用這兩種策略插入圖片的具體操作方法。
一、使用 disql 插入圖片
創建表
在插入圖片前,需創建相應的表結構,特別要注意將用于存儲圖片的列定義為 BLOB 類型。具體操作如下:
DROP TABLE IMAGE_LOB;
CREATE TABLE IMAGE_LOB (T_ID INT NOT NULL,T_IMAGE BLOB NOT NULL,PRIMARY KEY(T_ID)
);
在此表結構中,T_ID 作為主鍵,用于唯一標識每一條記錄;T_IMAGE 列則專門用于存儲圖片的二進制數據。
執行插入語句
打開 disql 工具后,可通過執行以下語句完成圖片插入操作:
@INSERT INTO IMAGE_LOB VALUES(1,@'F:\PIC\test.png');
COMMIT;
上述語句將位于F:\PIC\路徑下的test.png圖片插入到 IMAGE_LOB 表中,對應的記錄 ID 為 1。
二、通過 manager 調用系統包插入圖片
創建表
同樣,首先要創建表,并且將插入圖片的列定義為 BLOB 類型,操作語句與使用 disql 創建表時一致:
DROP TABLE IMAGE_LOB;
CREATE TABLE IMAGE_LOB (T_ID INT NOT NULL,T_IMAGE BLOB NOT NULL,PRIMARY KEY(T_ID)
);
創建圖片存放目錄
需要創建一個虛擬路徑目錄,用于存放待插入到表中的圖片。例如:
CREATE OR REPLACE DIRECTORY "IMAGES" AS 'F:\PIC';
此語句創建了一個名為 “IMAGES” 的虛擬目錄,其實際指向的物理路徑為F:\PIC。
創建存儲過程
接下來創建一個存儲過程,用于實現圖片插入操作。其中,FILENAME參數為圖片文件名,例如’test.png’。
CREATE OR REPLACE PROCEDURE IMG_INSERT(TID INT,FILENAME VARCHAR(200)
) ASF_LOB BFILE;B_LOB BLOB;
BEGININSERT INTO IMAGE_LOB (T_ID, T_IMAGE) VALUES (TID,EMPTY_BLOB()) RETURN T_IMAGE INTO B_LOB;F_LOB:= BFILENAME ('IMAGES', FILENAME);DBMS_LOB.FILEOPEN (F_LOB, DBMS_LOB.FILE_READONLY);DBMS_LOB.LOADFROMFILE (B_LOB, F_LOB, DBMS_LOB.GETLENGTH (F_LOB));DBMS_LOB.FILECLOSE (F_LOB);COMMIT;
END;
在這個存儲過程中,首先向 IMAGE_LOB 表中插入一條記錄,其中圖片字段先使用EMPTY_BLOB()占位。然后通過BFILENAME函數獲取圖片文件路徑,接著以只讀方式打開文件,并將文件內容加載到 BLOB 字段中,最后關閉文件并提交事務。
執行存儲過程
執行上述創建的存儲過程,即可實現圖片插入操作。例如:
CALL IMG_INSERT(1,'test.png');
這條語句會將test.png圖片插入到 IMAGE_LOB 表中,對應的記錄 ID 為 1。
查看表
插入完成后,可通過以下語句查看表中的數據:
SELECT * FROM IMAGE_LOB;
執行該查詢語句后,可看到表中已成功插入圖片相關記錄,其中圖片字段顯示為二進制數據。
在達夢數據庫實際應用場景里,不僅會有往數據庫表中插入圖片的需求,有時也需要從數據庫表中導出圖片。下面將詳細介紹在達夢數據庫中導出圖片的具體方法。
三、創建圖片導出目錄
在數據庫中定義一個虛擬目錄,用于指定圖片導出的本地路徑。執行以下SQL語句:
--定義本地圖片導出目錄
CREATE OR REPLACE DIRECTORY "IMAGES" AS 'D:\vm\FIC';
上述語句中,CREATE OR REPLACE DIRECTORY
用于創建或替換一個目錄對象,將名為IMAGES
的虛擬目錄映射到本地路徑D:\vm\FIC
。這個路徑是本地實際存在的目錄,用于存放導出的圖片。
四、創建導出圖片的存儲過程
通過創建存儲過程來實現從指定表中根據記錄ID導出圖片到之前定義的目錄中。
--導出圖片到本地dir
CREATE OR REPLACE PROCEDURE DUMP_IMAGE_TO_DIR(IN_TABLE_NAME VARCHAR2(1000), IN_ID INT)
ISL_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;L_SQL VARCHAR2(1000);
BEGINL_SQL := 'SELECT T_IMAGE FROM ' || IN_TABLE_NAME || ' WHERE T_ID = :1';EXECUTE IMMEDIATE L_SQL INTO L_BLOB USING IN_ID;L_BLOB_LEN := DBMS_LOB.GETLENGTH (L_BLOB);L_FILE := UTL_FILE.FOPEN ('IMAGES',IN_ID||'.JPG', 'WB', 32767);WHILE L_POS < L_BLOB_LENLOOPIF L_POS + L_AMOUNT -1 > L_BLOB_LEN THENL_AMOUNT := L_BLOB_LEN - L_POS + 1;END IF;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 OTHERS THENIF UTL_FILE.IS_OPEN (L_FILE) THENUTL_FILE.FCLOSE (L_FILE);END IF;RAISE;
END DUMP_IMAGE_TO_DIR;
- 參數說明:
IN_TABLE_NAME
:要從中導出圖片的表名,數據類型為VARCHAR2(1000)
。IN_ID
:對應表中圖片記錄的ID,數據類型為INT
。
- 變量定義:
L_FILE
:用于表示文件句柄,數據類型為UTL_FILE.FILE_TYPE
。L_BUFFER
:定義一個RAW
類型的緩沖區,大小為32767字節,用于臨時存儲從BLOB
字段中讀取的數據。L_AMOUNT
:每次從BLOB
字段讀取數據的長度,初始值為32767字節,數據類型為BINARY_INTEGER
。L_POS
:記錄當前讀取數據在BLOB
字段中的位置,初始值為1,數據類型為INTEGER
。L_BLOB
:用于存儲從表中查詢出來的圖片數據(BLOB
類型)。L_BLOB_LEN
:存儲BLOB
字段的長度,數據類型為INTEGER
。L_SQL
:用于構建動態SQL語句,數據類型為VARCHAR2(1000)
。
- 主要邏輯:
- 構建動態SQL語句,根據傳入的表名和ID查詢對應的圖片數據(
BLOB
類型)。 - 使用
DBMS_LOB.GETLENGTH
獲取BLOB
數據的長度。 - 使用
UTL_FILE.FOPEN
打開一個文件,文件名為傳入的ID加上.JPG
后綴,路徑為之前定義的IMAGES
虛擬目錄對應的本地路徑,以二進制寫模式打開。 - 通過循環讀取
BLOB
數據,并將讀取的數據寫入文件中。在循環過程中,根據剩余數據長度調整每次讀取的字節數,確保完整讀取BLOB
數據。 - 操作完成后,使用
UTL_FILE.FCLOSE
關閉文件。
- 構建動態SQL語句,根據傳入的表名和ID查詢對應的圖片數據(
- 異常處理:
- 如果在執行過程中發生其他異常,首先檢查文件是否打開,如果打開則關閉文件,然后重新拋出異常,以便上層調用能夠捕獲并處理異常。
五、調用存儲過程導出全表圖片
通過游標遍歷表中所有記錄的ID,調用上述存儲過程實現全表圖片的導出。
--調用導出過程把全表圖片導出
DECLARE CURSOR cur IS SELECT T_ID FROM IMAGE_LOB;
BEGINFOR rec IN cur LOOPDUMP_IMAGE_TO_DIR('IMAGE_LOB',rec.T_ID);END LOOP;
END;
- 定義游標:使用
CURSOR
定義一個游標cur
,用于查詢IMAGE_LOB
表中的所有T_ID
。 - 循環調用存儲過程:通過
FOR
循環遍歷游標cur
中的每一條記錄,將表名IMAGE_LOB
和當前記錄的T_ID
作為參數傳遞給DUMP_IMAGE_TO_DIR
存儲過程,實現逐張圖片導出到指定目錄。
通過以上步驟,就可以在達夢數據庫中實現從表中導出圖片的功能。在實際操作過程中,請確保相關路徑正確無誤,并且數據庫用戶具有相應的權限,以保證導出操作的順利進行。
綜上所述,在 達夢數據庫中,開發者可依據實際需求和應用場景,靈活選擇使用 disql 或通過 manager 調用系統包的方式插入圖片。以及使用存儲過程的方式導出圖片。不同方式各有優劣,在實際項目中,需綜合考量數據量、性能要求以及管理維護的便捷性等多方面因素,從而確定最適宜的圖片存儲和插入方案。