达梦数据库中插入导出图片的方法与应用

达梦数据库中插入导出图片的方法与应用

在数据库的实际应用场景中,图片存储是一项常见且重要的需求。以电商平台为例,商品展示图片是吸引消费者的关键元素;而在社交软件里,用户头像更是个人形象的直观体现。针对达梦数据库,业界常用的图片存储策略主要分为两大类。

第一种策略是将图片存储于磁盘,数据库字段仅记录图片路径。这种方式的显著优势在于减轻了数据库的存储压力,因为数据库无需直接处理图片的二进制数据。然而,它存在明显的局限性,一旦图片存储路径发生变更,或者存储磁盘出现故障,数据库应用在调用图片时就可能遭遇加载失败的问题。例如,若存储图片的磁盘分区因硬件故障损坏,依赖该路径的应用程序将无法正常显示相关图片。

第二种策略是将图片以二进制形式直接存储于数据库。达梦数据库采用这种方式,并支持使用 blob 或 bfile 类型的字段进行存储。这种策略的优势在于保障了数据的完整性和一致性,图片数据与其他相关数据集中存储于数据库,便于统一管理和维护。但高分辨率图片的二进制数据量往往较大,会显著增加数据库的存储负担。

接下来,详细介绍在 达梦数据库中利用这两种策略插入图片的具体操作方法。

一、使用 disql 插入图片

创建表

在插入图片前,需创建相应的表结构,特别要注意将用于存储图片的列定义为 BLOB 类型。具体操作如下:

sql 复制代码
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 工具后,可通过执行以下语句完成图片插入操作:

sql 复制代码
@INSERT INTO IMAGE_LOB VALUES(1,@'F:\PIC\test.png');
COMMIT;

上述语句将位于F:\PIC\路径下的test.png图片插入到 IMAGE_LOB 表中,对应的记录 ID 为 1。

二、通过 manager 调用系统包插入图片

创建表

同样,首先要创建表,并且将插入图片的列定义为 BLOB 类型,操作语句与使用 disql 创建表时一致:

sql 复制代码
DROP TABLE IMAGE_LOB;
CREATE TABLE IMAGE_LOB (
    T_ID INT NOT NULL,
    T_IMAGE BLOB NOT NULL,
    PRIMARY KEY(T_ID)
);

创建图片存放目录

需要创建一个虚拟路径目录,用于存放待插入到表中的图片。例如:

sql 复制代码
CREATE OR REPLACE DIRECTORY "IMAGES" AS 'F:\PIC';

此语句创建了一个名为 "IMAGES" 的虚拟目录,其实际指向的物理路径为F:\PIC。
创建存储过程

接下来创建一个存储过程,用于实现图片插入操作。其中,FILENAME参数为图片文件名,例如'test.png'。

sql 复制代码
CREATE OR REPLACE PROCEDURE IMG_INSERT(
    TID INT,
    FILENAME VARCHAR(200)
) AS
    F_LOB BFILE;
    B_LOB BLOB;
BEGIN
    INSERT 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 字段中,最后关闭文件并提交事务。
执行存储过程

执行上述创建的存储过程,即可实现图片插入操作。例如:

sql 复制代码
CALL IMG_INSERT(1,'test.png');

这条语句会将test.png图片插入到 IMAGE_LOB 表中,对应的记录 ID 为 1。
查看表

插入完成后,可通过以下语句查看表中的数据:

sql 复制代码
SELECT * FROM IMAGE_LOB;

执行该查询语句后,可看到表中已成功插入图片相关记录,其中图片字段显示为二进制数据。


在达梦数据库实际应用场景里,不仅会有往数据库表中插入图片的需求,有时也需要从数据库表中导出图片。下面将详细介绍在达梦数据库中导出图片的具体方法。

三、创建图片导出目录

在数据库中定义一个虚拟目录,用于指定图片导出的本地路径。执行以下SQL语句:

sql 复制代码
--定义本地图片导出目录
CREATE OR REPLACE DIRECTORY "IMAGES" AS 'D:\vm\FIC';

上述语句中,CREATE OR REPLACE DIRECTORY用于创建或替换一个目录对象,将名为IMAGES的虚拟目录映射到本地路径D:\vm\FIC。这个路径是本地实际存在的目录,用于存放导出的图片。

四、创建导出图片的存储过程

通过创建存储过程来实现从指定表中根据记录ID导出图片到之前定义的目录中。

sql 复制代码
--导出图片到本地dir
CREATE OR REPLACE PROCEDURE DUMP_IMAGE_TO_DIR(IN_TABLE_NAME VARCHAR2(1000),  IN_ID          INT)
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;
    L_SQL      VARCHAR2(1000);
BEGIN
    L_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_LEN
    LOOP
        IF L_POS + L_AMOUNT -1 > L_BLOB_LEN THEN
            L_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 THEN
    IF UTL_FILE.IS_OPEN (L_FILE) THEN
        UTL_FILE.FCLOSE (L_FILE);
    END IF;
    RAISE;
END DUMP_IMAGE_TO_DIR;
  1. 参数说明
    • IN_TABLE_NAME:要从中导出图片的表名,数据类型为VARCHAR2(1000)
    • IN_ID:对应表中图片记录的ID,数据类型为INT
  2. 变量定义
    • 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)
  3. 主要逻辑
    • 构建动态SQL语句,根据传入的表名和ID查询对应的图片数据(BLOB类型)。
    • 使用DBMS_LOB.GETLENGTH获取BLOB数据的长度。
    • 使用UTL_FILE.FOPEN打开一个文件,文件名为传入的ID加上.JPG后缀,路径为之前定义的IMAGES虚拟目录对应的本地路径,以二进制写模式打开。
    • 通过循环读取BLOB数据,并将读取的数据写入文件中。在循环过程中,根据剩余数据长度调整每次读取的字节数,确保完整读取BLOB数据。
    • 操作完成后,使用UTL_FILE.FCLOSE关闭文件。
  4. 异常处理
    • 如果在执行过程中发生其他异常,首先检查文件是否打开,如果打开则关闭文件,然后重新抛出异常,以便上层调用能够捕获并处理异常。

五、调用存储过程导出全表图片

通过游标遍历表中所有记录的ID,调用上述存储过程实现全表图片的导出。

sql 复制代码
--调用导出过程把全表图片导出
DECLARE 
	CURSOR cur IS 
		SELECT T_ID FROM IMAGE_LOB;
BEGIN
	FOR rec IN cur LOOP
		DUMP_IMAGE_TO_DIR('IMAGE_LOB',rec.T_ID);
  END LOOP;
END;
  1. 定义游标 :使用CURSOR定义一个游标cur,用于查询IMAGE_LOB表中的所有T_ID
  2. 循环调用存储过程 :通过FOR循环遍历游标cur中的每一条记录,将表名IMAGE_LOB和当前记录的T_ID作为参数传递给DUMP_IMAGE_TO_DIR存储过程,实现逐张图片导出到指定目录。

通过以上步骤,就可以在达梦数据库中实现从表中导出图片的功能。在实际操作过程中,请确保相关路径正确无误,并且数据库用户具有相应的权限,以保证导出操作的顺利进行。

综上所述,在 达梦数据库中,开发者可依据实际需求和应用场景,灵活选择使用 disql 或通过 manager 调用系统包的方式插入图片。以及使用存储过程的方式导出图片。不同方式各有优劣,在实际项目中,需综合考量数据量、性能要求以及管理维护的便捷性等多方面因素,从而确定最适宜的图片存储和插入方案。

相关推荐
Tipriest_22 分钟前
Ubuntu常用的软件格式deb, rpm, dmg, AppImage等打包及使用方法
linux·运维·ubuntu
背太阳的牧羊人23 分钟前
Neo4j 的向量搜索(Neo4jVector)和常见的向量数据库(比如 Milvus、Qdrant)之间的区别与联系
数据库·neo4j·milvus
真智AI37 分钟前
利用 Claude Opus 4 自动化 GitHub 工作流:从安装到实战详解
运维·自动化·github
liulun38 分钟前
在浏览器中使用SQLite(官方sqlite3.wasm)
数据库·sqlite·wasm
胡斌附体1 小时前
linux测试端口是否可被外部访问
linux·运维·服务器·python·测试·端口测试·临时服务器
愚润求学2 小时前
【Linux】自旋锁和读写锁
linux·运维
大锦终2 小时前
【Linux】常用基本指令
linux·运维·服务器·centos
IT项目管理2 小时前
达梦数据库DMHS介绍及安装部署
linux·数据库
你都会上树?2 小时前
MySQL MVCC 详解
数据库·mysql
大春儿的试验田2 小时前
高并发收藏功能设计:Redis异步同步与定时补偿机制详解
java·数据库·redis·学习·缓存