UTL_COMPRESS 包

UTL_COMPRESS 包提供对输入的 BLOB、VARBINARY 或 BFILE 类型数据进行压缩或解压的功能。压缩与解压的格式兼容 gzip(-n),压缩时支持指定压缩等级,且支持分段压缩或解压。

UTL_COMPRESS 包解压时支持的最大解压比例和解压后数据的最大长度受 INI 参数 MAX_UNCOMPRESS_RATIO 和 MAX_UNCOMPRESS_LENGTH 的限制,具体可参考《DM8 系统管理员手册》2.1.1.1.8 节。

调用 UTL_COMPRESS 包中的相关函数和过程时需要保证 DM 安装目录的 bin 子目录下存在 libz.dll(windows)或 libz.so(linux)库文件,否则报错。

42.1 相关方法

下面对各个函数和过程进行详细说明。

  1. LZ_COMPRESS

对数据进行压缩。

语法如下:

CopyFUNCTION LZ_COMPRESS(
	SRC			IN			VARBINARY,
   	QUALITY		IN			INTEGER 			DEFAULT 6
) RETURN VARBINARY;
FUNCTION LZ_COMPRESS(
	SRC			IN			BLOB,
   	QUALITY		IN			INTEGER 			DEFAULT 6
) RETURN BLOB;
FUNCTION LZ_COMPRESS(
	SRC			IN			BFILE,
   	QUALITY		IN			INTEGER 			DEFAULT 6
) RETURN BLOB;
PROCEDURE LZ_COMPRESS(
	SRC			IN			BLOB,
	DST			IN OUT 		BLOB,
   	QUALITY		IN			INTEGER 			DEFAULT 6
);
PROCEDURE LZ_COMPRESS(
	SRC			IN			BFILE,
	DST			IN OUT 		BLOB,
   	QUALITY		IN			BINARY_INTEGER 	DEFAULT 6
);

参数详解

● SRC 输入参数,VARBINARY、BLOB 或 BFILE 类型的待压缩数据。

● QUALITY 输入参数,压缩等级。取值范围 1~9:1 表示 1 级压缩;2 表示 2 级压缩;9 表示 9 级压缩。压缩级别越高,压缩速度越慢,但压缩比越高。默认值为 6。

● DST 输入输出参数,压缩结果。LZ_COMPRESS 过程是将压缩数据返回到现有的 BLOB 类型参数 DST 中,因此当参数 DST 为空时,将报错处理。

返回值

压缩结果。若待压缩数据类型为 VARBINARY,则压缩结果的数据类型也为 VARBINARY;若待压缩数据类型为 BLOB 或 BFILE,则压缩结果的数据类型均为 BLOB。

使用说明:

(1) 待压缩数据不能为空,否则报错;

(2) 若压缩结果的数据类型为 VARBINARY,且压缩结果的数据长度超过 32767 个字节,则返回空;

(3) 若待压缩数据类型为 BFILE,则需要首先调用 DBMS_LOB.FILEOPEN 打开 BFILE,否则报错;

(4) 压缩等级必须在合法范围内,否则报错;

(5) 若返回值类型为 BLOB,或输出参数为临时 BLOB 大对象,则需要调用 DBMS_LOB.FREETEMPORARY 释放临时的 BLOB 大对象;

(6) ORACLE 与 DM 对数据的压缩结果不一定完全相同,但得到压缩数据都可以被 ORACLE 或 DM 解压。

  1. LZ_UNCOMPRESS

对数据进行解压。

语法如下:

CopyFUNCTION LZ_UNCOMPRESS(
	SRC			IN			VARBINARY
) RETURN VARBINARY;
FUNCTION LZ_UNCOMPRESS(
	SRC			IN			BLOB
) RETURN BLOB;
FUNCTION LZ_UNCOMPRESS(
	SRC			IN			BFILE
) RETURN BLOB;
PROCEDURE LZ_UNCOMPRESS(
	SRC			IN			BLOB,
	DST			IN OUT		BLOB
);
PROCEDURE LZ_UNCOMPRESS(
	SRC			IN			BFILE,
	DST			IN OUT		BLOB
);

参数详解

● SRC 输入参数,VARBINARY、BLOB 或 BFILE 类型的待解压数据。

● DST 输入输出参数,解压结果。

返回值

解压结果。若待解压数据类型为 VARBINARY,则解压结果的数据类型也为 VARBINARY;若待解压数据类型为 BLOB 或 BFILE,则解压结果的数据类型均为 BLOB。

使用说明:

(1) 待解压数据不能为空,否则报错;

(2) 若解压结果的数据类型为 VARBINARY,且解压结果的数据长度超过 32767 个字节,则返回空;

(3) 若待解压数据类型为 BFILE,则需要首先调用 DBMS_LOB.FILEOPEN 打开 BFILE,否则报错;

(4) 若返回值类型为 BLOB,或输出参数为临时 BLOB 大对象,则需要调用 DBMS_LOB.FREETEMPORARY 释放临时的 BLOB 大对象。

  1. ISOPEN

判断句柄是否打开。

语法如下:

CopyFUNCTION ISOPEN(
	HANDLE			IN		INTEGER
) RETURN BOOLEAN;

参数详解

● HANDLE 输入参数,句柄。用 1~5 之间的 5 个整型数字表示句柄,详细介绍请参考 LZ_COMPRESS_OPEN 函数的使用说明。

返回值

TRUE:句柄已打开。

FALSE:句柄未打开。

  1. LZ_COMPRESS_OPEN

打开一个压缩句柄,指定一个 BLOB 大对象用于存放压缩结果。

语法如下:

CopyFUNCTION LZ_COMPRESS_OPEN (
	DST			IN OUT		BLOB,
   	QUALITY   	IN			INTEGER 		DEFAULT 6
) RETURN INTEGER;

参数详解

● DST 输入输出参数,用于存放压缩结果的 BLOB 大对象。

● QUALITY 输入参数,压缩等级。取值范围 1~9:1 表示 1 级压缩;2 表示 2 级压缩;9 表示 9 级压缩。压缩级别越高,压缩速度越慢,但压缩比越高。默认值为 6。

返回值

压缩句柄的对应值。

使用说明:

(1) BLOB 大对象不能为空,否则报错;

(2) 压缩等级必须在合法范围内,否则报错;

(3) 每个会话最多打开 5 个压缩或解压句柄,分别用 1~5 之间的 5 个整数表示,若打开句柄的个数超过 5 个,则报错。调用 LZ_COMPRESS_OPEN 函数时会优先打开已关闭的句柄中值较小的句柄,例如:新建一个会话,打开三个句柄,则返回三个值为 1、2、3 的句柄,关闭值为 2 的句柄,再打开三个句柄,则返回三个值为 2、4、5 的句柄,由于此时打开的句柄个数为 5 个,若继续打开句柄,则报错。

  1. LZ_COMPRESS_ADD

按照压缩句柄指定的压缩等级,压缩数据。

语法如下:

CopyPROCEDURE LZ_COMPRESS_ADD (
	HANDLE 		IN			INTEGER,
	DST			IN OUT		BLOB,
	SRC 		IN			VARBINARY
);

参数详解

● HANDLE 输入参数,压缩句柄。用 1~5 之间的 5 个整型数字表示句柄,详细介绍请参考 LZ_COMPRESS_OPEN 函数的使用说明。

● DST 输入输出参数,压缩句柄对应的 BLOB 大对象,用于存放压缩结果。

● SRC 输入参数,待压缩数据。

使用说明:

(1) 用户需要提前打开压缩句柄,否则报错;

(2) 压缩句柄必须与 BLOB 大对象相对应,否则报错;

(3) 待压缩数据与 BLOB 大对象均不能为空,否则报错;

(4) LZ_COMPRESS_ADD 执行过程中会随时将压缩数据更新到 BLOB 大对象中,更新的压缩数据将被添加到 BLOB 大对象的末尾。

  1. LZ_COMPRESS_CLOSE

将缓存中的压缩数据全部写入 BLOB 大对象,关闭压缩句柄。

语法如下:

CopyPROCEDURE LZ_COMPRESS_CLOSE (
	HANDLE 		IN			INTEGER,
	DST			IN OUT		BLOB
);

参数详解

● HANDLE 输入参数,压缩句柄。用 1~5 之间的 5 个整型数字表示句柄,详细介绍请参考 LZ_COMPRESS_OPEN 函数的使用说明。

● DST 输入输出参数,压缩句柄对应的 BLOB 大对象,用于存放压缩结果。

使用说明:

(1) 若压缩句柄已经处于关闭状态,则报错;

(2) 压缩句柄必须与 BLOB 大对象相对应,否则报错;

(3) 若执行 LZ_COMPRESS_OPEN 后并未执行 LZ_COMPRESS_ADD,则压缩结果为空,即 BLOB 大对象为空,执行 LZ_COMPRESS_OPEN 时 BLOB 大对象的初始值不会影响最后的结果。

  1. LZ_UNCOMPRESS_OPEN

打开一个解压句柄,指定一个待解压的 BLOB 大对象。

语法如下:

CopyFUNCTION LZ_UNCOMPRESS_OPEN(
	SRC			IN		BLOB
) RETURN BINARY_INTEGER;

参数详解

● SRC 输入参数,待解压的 BLOB 大对象。

返回值

解压句柄的对应值。

使用说明:

(1) BLOB 大对象不能为空,否则报错;

(2) 该函数返回句柄值的策略与 LZ_COMPRESS_OPEN 相同,详细介绍请参考 LZ_COMPRESS_OPEN 函数的使用说明。

  1. LZ_UNCOMPRESS_EXTRACT

从上次解压结束的位置,继续解压句柄对应的 BLOB 大对象。

语法如下:

CopyPROCEDURE LZ_UNCOMPRESS_EXTRACT(
	HANDLE 		IN		INTEGER,
	DST			OUT		VARBINARY
);
PROCEDURE LZ_UNCOMPRESS_EXTRACT(
	HANDLE 		IN		INTEGER,
	DST			OUT		VARBINARY,
	OUTLEN		IN		INTEGER
);

参数详解

● HANDLE 输入参数,解压句柄。用 1~5 之间的 5 个整型数字表示句柄,详细介绍请参考 LZ_COMPRESS_OPEN 函数的使用说明。

● DST 输出参数,解压结果。

● OUTLEN 输入参数,指定解压的数据长度。取值范围为[0,32767],单位:字节。

使用说明:

(1) 用户需要提前打开解压句柄,否则报错;

(2) 若调用 LZ_UNCOMPRESS_EXTRACT 时解压句柄对应的 BLOB 大对象已经全部解压完成,则报错;

(3) 若待解压数据过长导致无法被完全解压,则 ORACLE 会根据输出参数 DST 的定义长度,解压相应长度的数据存放在 DST 中,DM 不支持上述策略,当待解压数据无法被完全解压时,调用两个参数的 LZ_UNCOMPRESS_EXTRACT 将始终解压 32767 个字节长度的数据,为此,DM 提供三个参数的 LZ_UNCOMPRESS_EXTRACT,用户可通过 OUTLEN 参数指定解压的数据长度;

(4) 若调用 LZ_UNCOMPRESS_EXTRACT 时,解压句柄对应的 BLOB 大对象还未开始解压,则将检查该 BLOB 大对象是否有 GZIP 格式的压缩头,若没有则报错;

(5) 若解压句柄对应的 BLOB 大对象已经解压完成,则会对该 BLOB 大对象进行 CRC 校验,若校验失败则报错;

(6) ORACLE 对第一次执行 LZ_UNCOMPRESS_EXTRACT 时的待解压 BLOB 大对象中的内容进行解压,而 DM 对执行 LZ_UNCOMPRESS_OPEN 时的待解压 BLOB 大对象中的内容进行解压。即若用户在执行 LZ_UNCOMPRESS_OPEN 之后,且在第一次执行 LZ_UNCOMPRESS_EXTRACT 之前修改了待解压 BLOB 大对象中的内容,则 ORACLE 的解压结果会相应改变,但 DM 的解压结果不会发生变化。但若用户在执行 LZ_UNCOMPRESS_EXTRACT 之后修改了待解压 BLOB 大对象中的内容,则 ORACLE 和 DM 的解压结果均不会发生变化。

  1. LZ_UNCOMPRESS_CLOSE

关闭解压句柄。

语法如下:

CopyPROCEDURE LZ_UNCOMPRESS_CLOSE(
	HANDLE 		IN		INTEGER
);

参数详解

● HANDLE 输入参数,解压句柄。用 1~5 之间的 5 个整型数字表示句柄,详细介绍请参考 LZ_COMPRESS_OPEN 函数的使用说明。

使用说明:

若解压句柄已经处于关闭状态,则报错。

42.2 举例说明

使用包内的过程和函数之前,如果还未创建过系统包,请先调用系统过程 SP_CREATE_SYSTEM_PACKAGES 创建系统包。

CopySP_CREATE_SYSTEM_PACKAGES(1,'UTL_COMPRESS');

准备如下数据:

CopyCREATE TABLE BFILE_TABLE(ID NUMBER,BFILE_COLUMN BFILE);
CREATE DIRECTORY MYBFILE AS 'D:\testxml\bfile';
INSERT INTO BFILE_TABLE VALUES (1,BFILENAME('MYBFILE','bfiletest.txt'));
CREATE TABLE BLOB_TABLE(ID NUMBER,BLOB_COLUMN BLOB);
COMMIT;

其中,D:\testxml\bfile 目录下的 bfiletest.txt 文件中的内容如下:

Copy《红楼梦》写的是封建贵族的青年贾宝玉、林黛王、薛宝钗之间的恋爱和婚姻悲剧,而且以此为中心,写出了当时具有代表性的贾、王、史、薛四大家族的兴衰,其中又以贾府为中心,揭露了封建社会后期的种种黑暗和罪恶,及其不可克服的内在矛盾,对腐朽的封建统治阶级和行将崩溃的封建制度作了有力的批判,使读者预感到它必然要走向覆灭的命运。

例 1 LZ_COMPRESS 函数的使用。

一 从 BFILE 文件中读取数据并进行压缩。

CopyDECLARE
  SRC_BFILE BFILE;
  DST_BLOB BLOB;
BEGIN
  SELECT BFILE_COLUMN INTO SRC_BFILE FROM BFILE_TABLE WHERE ID=1 FOR UPDATE;
  DBMS_LOB.OPEN(SRC_BFILE);  //打开BFILE文件
  DST_BLOB := UTL_COMPRESS.LZ_COMPRESS(SRC_BFILE,6);  //进行数据压缩
	INSERT INTO BLOB_TABLE VALUES(1,DST_BLOB);
END;

二 查询压缩结果。

CopySELECT * FROM BLOB_TABLE WHERE ID=1;
//查询结果如下:
ID		   BLOB_COLUMN
---------- -----------------------------------------------------------------
1  
0x1F8B08000000000000034D90D16E82301486EFF7D4A096A1A8A05B86933AA243D1250833C8B4157D187B4ECBD55E61AD2ECB925E347F4FBEEF3FBD5A3DC916B83CE16275B53C705EE5B483931C0A1B3853E51E435F27CD6C0CC7529567D8CEE4B07BB56C7C0B1B1EC9A1A7EFEA25D279330EC5D16BC2D2106C4FBA9F30EEC3660A29C7D60EBAE9F7A9AFACBE383C0BBEC42C1107260E195CDA3AD75E78648239503F615801F942DA15FC5DCDD768A51AA8D55A74D781BFFB95461124296CAB7B4920A59A1786462A43F65D2D329D19FDEF423F6BE8CEB86E3BCAE42C4E53088648630D91E9409F868F701AEAFEB2FE40BB324CBF77C30EC0CF81784807C6E810A06B1947323A9B99FCA84880B4364F77388F71C79B492559AA696ADE87C2817283ACFD37036E056C256AAA2BE9ADA117990FEC1EC14D3453D4179573659166D1C14E0C6E01DB365C88EC546A65AB7D01C148AD1C69670638AAD525B85AAD871F26B4024BD8010000

例 2 LZ_UNCOMPRESS 函数的使用。

一 对给定的压缩数据进行解压。

CopyDECLARE
	SRC_BLOB BLOB;
	DST_BLOB BLOB;
BEGIN
SRC_BLOB:=HEXTORAW('1F8B080000000000000BBB70EEC8B56B17CE1DB940777A204D24CF0E004F3D66292C010000');    //符合校验的压缩数据
  DST_BLOB := UTL_COMPRESS.LZ_UNCOMPRESS(SRC_BLOB);  //进行数据解压
	INSERT INTO BLOB_TABLE VALUES(2,DST_BLOB);
END;

二 查询解压结果。

CopySELECT * FROM BLOB_TABLE WHERE ID=2;
//查询结果如下:
ID		   BLOB_COLUMN
---------- -----------------------------------------------------------------
2            0xD0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0

例 3 分段压缩。

一 对给定的数据进行分段压缩。

CopyDECLARE
  V_HANDLE BINARY_INTEGER;
  DST_BLOB BLOB;
SRC_VAR VARBINARY;
BEGIN
SRC_VAR:=HEXTORAW('D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0');
DBMS_LOB.CREATETEMPORARY(DST_BLOB, TRUE);  //创建临时BLOB大对象
V_HANDLE :=UTL_COMPRESS.LZ_COMPRESS_OPEN(DST_BLOB,5);  //打开压缩句柄
UTL_COMPRESS.LZ_COMPRESS_ADD(V_HANDLE,DST_BLOB,SRC_VAR);  //进行分段压缩
  UTL_COMPRESS.LZ_COMPRESS_CLOSE(V_HANDLE,DST_BLOB);  //关闭压缩句柄
  INSERT INTO BLOB_TABLE VALUES(3,DST_BLOB);
DBMS_LOB.FREETEMPORARY(DST_BLOB);  //释放临时BLOB大对象
END;

二 查询分段压缩结果。

CopySELECT * FROM BLOB_TABLE WHERE ID=3;
//查询结果如下:
ID		   BLOB_COLUMN
---------- -----------------------------------------------------------------
3            0x1F8B0800000000000003BB70EEC8B56B17CE1DB940779AB00A5269C22A4857894C03004F3D66292C010000

例 4 分段解压。

一 对给定的压缩数据进行分段解压。

CopyDECLARE
  SRC_BLOB BLOB;
  DST_TEMP VARBINARY;
  DST_OUT BLOB;
  V_HANDLE BINARY_INTEGER;
BEGIN
SRC_BLOB:=HEXTORAW('1F8B080000000000000BBB70EEC8B56B17CE1DB940777A204D24CF0E004F3D66292C010000');  //符合校验的压缩数据
  V_HANDLE :=UTL_COMPRESS.LZ_UNCOMPRESS_OPEN(SRC_BLOB); //打开解压句柄
  DBMS_LOB.CREATETEMPORARY(DST_OUT, TRUE);  //创建临时BLOB大对象
//利用循环结构进行分段解压
LOOP
  BEGIN
	UTL_COMPRESS.LZ_UNCOMPRESS_EXTRACT(V_HANDLE, DST_TEMP);
	EXCEPTION
		WHEN OTHERS THEN
    EXIT;
  END;
  DBMS_LOB.APPEND(DST_OUT, DST_TEMP);
END LOOP;
UTL_COMPRESS.LZ_UNCOMPRESS_CLOSE(V_HANDLE);	//关闭解压句柄
INSERT INTO BLOB_TABLE VALUES(4,DST_OUT);
DBMS_LOB.FREETEMPORARY(DST_OUT);  //释放临时BLOB大对象
END;

二 查询分段解压结果。

CopySELECT * FROM BLOB_TABLE WHERE ID=4;
查询结果为:
ID		   BLOB_COLUMN
---------- -----------------------------------------------------------------
4            0xD0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0
微信扫码
分享文档
扫一扫
联系客服